Docfile commited on
Commit
6ade419
·
verified ·
1 Parent(s): 41554ba

Upload index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +62 -253
templates/index.html CHANGED
@@ -1,70 +1,37 @@
 
1
  <!DOCTYPE html>
2
  <html lang="fr">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>Mariam M-0 | Solution Mathématique</title>
7
- <!-- Tailwind CSS -->
8
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
9
 
10
- <!-- Configuration optimisée de MathJax pour expressions complexes -->
11
  <script>
12
  window.MathJax = {
13
  tex: {
14
- inlineMath: [['$', '$'], ['\\(', '\\)']],
15
- displayMath: [['$$', '$$'], ['\\[', '\\]']],
16
  processEscapes: true,
17
- processEnvironments: true,
18
- macros: {
19
- R: '{\\mathbb{R}}',
20
- N: '{\\mathbb{N}}',
21
- Z: '{\\mathbb{Z}}',
22
- C: '{\\mathbb{C}}',
23
- Q: '{\\mathbb{Q}}'
24
- },
25
- packages: {
26
- '[+]': [
27
- 'autoload',
28
- 'ams',
29
- 'noerrors',
30
- 'physics',
31
- 'colorv2',
32
- 'cancel',
33
- 'mhchem'
34
- ]
35
- },
36
- // Ignorer les erreurs
37
- processClass: "math",
38
- formatError: (jax, err) => {
39
- console.warn('Erreur MathJax:', err);
40
- return jax.formatError(err);
41
- }
42
- },
43
- svg: {
44
- fontCache: 'global',
45
- scale: 1.2
46
  },
 
47
  options: {
48
- enableMenu: true,
49
- skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'code'],
50
- renderActions: {
51
- assistiveMml: []
52
- }
53
- },
54
- loader: {
55
- load: ['[tex]/physics', '[tex]/ams', '[tex]/colorv2', '[tex]/cancel', '[tex]/mhchem']
56
  },
57
  startup: {
58
  pageReady: () => {
59
  console.log('MathJax est complètement chargé.');
60
  window.mathJaxReady = true;
61
- document.dispatchEvent(new Event('mathjax-ready'));
62
  }
63
  }
64
  };
65
  </script>
66
- <!-- Chargement du module SVG pour un meilleur rendu -->
67
- <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js" id="MathJax-script" async></script>
68
  <script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.min.js"></script>
69
 
70
  <style>
@@ -74,7 +41,6 @@
74
  font-family: 'Space Grotesk', sans-serif;
75
  }
76
 
77
- /* CSS existant... */
78
  .uploadArea {
79
  background: #f3f4f6;
80
  border: 2px dashed #d1d5db;
@@ -134,49 +100,24 @@
134
  margin-left: 8px;
135
  }
136
 
137
- /* Styles pour les équations MathJax */
138
- mjx-container {
139
- display: inline-block;
140
- overflow-x: auto;
141
- overflow-y: hidden;
142
- max-width: 100%;
143
- padding: 0.5em 0;
144
- min-width: auto !important;
145
- }
146
-
147
- mjx-container[jax="SVG"] {
148
- direction: ltr;
149
- }
150
-
151
- mjx-container svg {
152
- min-width: auto !important;
153
- }
154
-
155
- /* Amélioration pour les formules complexes */
156
- mjx-mtable {
157
- min-width: auto !important;
158
- margin: 0 !important;
159
- }
160
-
161
- /* Support des tableaux et autres éléments */
162
  table {
163
  border-collapse: collapse;
164
  width: 100%;
165
- margin: 1rem 0;
166
  }
167
  th, td {
168
  border: 1px solid #d1d5db;
169
- padding: 0.75rem;
170
  text-align: left;
171
  }
172
  th {
173
  background-color: #f3f4f6;
174
  font-weight: 600;
175
  }
176
-
177
- /* Intégration MathJax et tables */
178
- mjx-container + table, table + mjx-container {
179
- margin-top: 1rem;
180
  }
181
  </style>
182
  </head>
@@ -188,7 +129,6 @@
188
  </header>
189
 
190
  <main>
191
- <!-- Le reste du HTML reste inchangé -->
192
  <form id="problemForm" class="space-y-6" novalidate>
193
  <!-- Zone de dépôt et sélection d'image -->
194
  <div class="uploadArea p-8 text-center relative" aria-label="Zone de dépôt d'image">
@@ -234,6 +174,7 @@
234
  </div>
235
  <div class="border-t pt-6">
236
  <h3 class="text-xl font-bold text-gray-800 mb-4">Solution</h3>
 
237
  <div id="answerContent" class="text-gray-700 table-responsive"></div>
238
  </div>
239
  </section>
@@ -260,8 +201,7 @@
260
  let thoughtsBuffer = '';
261
  let answerBuffer = '';
262
  let currentMode = null;
263
- let updateTimeout = null;
264
- let mathJaxQueue = Promise.resolve();
265
 
266
  // Mise à jour de l'affichage du temps écoulé
267
  const updateTimestamp = () => {
@@ -317,126 +257,38 @@
317
  handleFileSelect(e.dataTransfer.files[0]);
318
  });
319
 
320
- // Méthode améliorée pour traiter le LaTeX dans Markdown
321
- const processContent = (content) => {
322
- // Génération de jetons uniques pour éviter les collisions
323
- const createToken = (index) => `__LATEX_${Date.now()}_${index}__`;
324
-
325
- // Stockage des expressions LaTeX
326
- const latexBlocks = [];
327
-
328
- // Identification de tous les types d'expressions LaTeX
329
- const latexPattern = /(\$\$[\s\S]*?\$\$|\$[^\$\n]+?\$|\\begin\{[a-z]*\}[\s\S]*?\\end\{[a-z]*\})/g;
330
-
331
- // Étape 1: Remplacer les expressions LaTeX par des jetons
332
- const tokenizedContent = content.replace(latexPattern, (match) => {
333
- const token = createToken(latexBlocks.length);
334
- latexBlocks.push({token, latex: match});
335
- // Encadrer le jeton d'une manière qui empêche marked de le transformer
336
- return `<!${token}!>`;
337
- });
338
-
339
- // Étape 2: Traiter avec marked
340
- let htmlContent = marked.parse(tokenizedContent);
341
-
342
- // Étape 3: Restaurer les expressions LaTeX
343
- latexBlocks.forEach(({token, latex}) => {
344
- // Échapper les caractères spéciaux dans le jeton
345
- const escapedToken = token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
346
- const tokenPattern = new RegExp(`<!${escapedToken}!>`, 'g');
347
- htmlContent = htmlContent.replace(tokenPattern, latex);
348
- });
349
-
350
- return htmlContent;
351
- };
352
-
353
- // Fonction pour le rendu MathJax
354
- const typesetMathJax = async (element) => {
355
- if (!window.mathJaxReady) {
356
- return new Promise((resolve) => {
357
- document.addEventListener('mathjax-ready', () => {
358
- typesetMathJax(element).then(resolve);
359
- }, { once: true });
360
- });
361
- }
362
-
363
- try {
364
- // Utiliser une file d'attente pour éviter les conflits de rendu
365
- return mathJaxQueue = mathJaxQueue.then(async () => {
366
- try {
367
- MathJax.startup.document.elements = [element];
368
- await MathJax.typesetPromise([element]);
369
- return true;
370
- } catch (error) {
371
- console.warn('Erreur dans le rendu MathJax', error);
372
- // Essayer de réparer certaines expressions couramment problématiques
373
- const fixLaTeX = (elem) => {
374
- // Remplacer les caractères problématiques
375
- elem.innerHTML = elem.innerHTML
376
- .replace(/\\{/g, '\\lbrace ')
377
- .replace(/\\}/g, '\\rbrace ')
378
- .replace(/(?<![\\])\{/g, '\\{')
379
- .replace(/(?<![\\])\}/g, '\\}');
380
- };
381
-
382
- // Appliquer les corrections et retenter
383
- const mathElements = element.querySelectorAll('mjx-container');
384
- mathElements.forEach(fixLaTeX);
385
-
386
- try {
387
- await MathJax.typesetPromise([element]);
388
- return true;
389
- } catch (retryError) {
390
- console.error('Échec de la récupération MathJax', retryError);
391
- return false;
392
- }
393
- }
394
- });
395
- } catch (fatalError) {
396
- console.error('Erreur fatale MathJax', fatalError);
397
- return false;
398
  }
399
  };
400
 
401
- // Fonction pour mettre à jour l'affichage
402
  const updateDisplay = async () => {
403
- try {
404
- // Appliquer le traitement au contenu
405
- thoughtsContent.innerHTML = processContent(thoughtsBuffer);
406
- answerContent.innerHTML = processContent(answerBuffer);
407
-
408
- // Rendu MathJax
409
- await typesetMathJax(thoughtsContent);
410
- await typesetMathJax(answerContent);
411
-
412
- // Scroll vers le bas
413
- if (currentMode === 'thinking') {
414
- thoughtsContent.scrollTop = thoughtsContent.scrollHeight;
415
- } else if (currentMode === 'answering') {
416
- answerContent.scrollTop = answerContent.scrollHeight;
417
- }
418
- } catch (error) {
419
- console.error('Erreur lors de la mise à jour de l\'affichage', error);
420
- }
421
-
422
- // Réinitialiser le timeout
423
  updateTimeout = null;
424
  };
425
 
426
  // Fonction pour planifier la mise à jour (dé-bounce)
427
  const scheduleUpdate = () => {
428
- if (updateTimeout) {
429
- clearTimeout(updateTimeout);
430
- }
431
- updateTimeout = setTimeout(updateDisplay, 300);
432
  };
433
 
434
- // Configuration de marked
435
  marked.setOptions({
436
  gfm: true,
437
- breaks: true,
438
- pedantic: false,
439
- smartLists: true
440
  });
441
 
442
  // Soumission du formulaire
@@ -469,10 +321,6 @@
469
  body: formData
470
  });
471
 
472
- if (!response.ok) {
473
- throw new Error(`Erreur HTTP: ${response.status}`);
474
- }
475
-
476
  const reader = response.body.getReader();
477
  const decoder = new TextDecoder();
478
  let buffer = '';
@@ -480,42 +328,27 @@
480
  // Traitement d'un chunk de données
481
  const processChunk = async chunk => {
482
  buffer += decoder.decode(chunk, { stream: true });
483
- // Recherche des délimiteurs de message complets
484
- const lines = [];
485
- let startPos = 0;
486
- let endPos;
487
-
488
- while ((endPos = buffer.indexOf('\n\n', startPos)) !== -1) {
489
- lines.push(buffer.substring(startPos, endPos));
490
- startPos = endPos + 2;
491
- }
492
-
493
- // Conserver la dernière partie potentiellement incomplète
494
- buffer = buffer.substring(startPos);
495
 
496
  for (const line of lines) {
497
  if (!line.startsWith('data:')) continue;
498
- try {
499
- const data = JSON.parse(line.slice(5));
500
 
501
- if (data.mode) {
502
- currentMode = data.mode;
503
- loader.classList.add('hidden');
504
- solutionSection.classList.remove('hidden');
505
- }
506
- if (data.content) {
507
- if (currentMode === 'thinking') {
508
- thoughtsBuffer += data.content;
509
- } else if (currentMode === 'answering') {
510
- answerBuffer += data.content;
511
- }
512
  }
513
- } catch (error) {
514
- console.error('Erreur de parsing JSON:', error, line);
515
  }
516
  }
517
-
518
- // Planifier la mise à jour
519
  scheduleUpdate();
520
  };
521
 
@@ -523,28 +356,18 @@
523
  while (true) {
524
  const { done, value } = await reader.read();
525
  if (done) {
526
- // Traitement final si nécessaire
527
- if (buffer.length > 5 && buffer.startsWith('data:')) {
528
- try {
529
- const data = JSON.parse(buffer.slice(5));
530
- if (data.content) {
531
- if (currentMode === 'thinking') {
532
- thoughtsBuffer += data.content;
533
- } else if (currentMode === 'answering') {
534
- answerBuffer += data.content;
535
- }
536
  }
537
- } catch (e) {
538
- console.warn('Impossible de parser le dernier fragment:', e);
539
  }
540
  }
541
-
542
- // Forcer une mise à jour finale
543
- if (updateTimeout) {
544
- clearTimeout(updateTimeout);
545
- updateTimeout = null;
546
- }
547
- await updateDisplay();
548
  break;
549
  }
550
  await processChunk(value);
@@ -552,25 +375,11 @@
552
  stopTimer();
553
  } catch (error) {
554
  console.error('Erreur:', error);
555
- alert(`Une erreur est survenue: ${error.message}`);
556
  loader.classList.add('hidden');
557
  stopTimer();
558
  }
559
  });
560
-
561
- // Fonction de débogage pour tester le rendu LaTeX
562
- window.testLatex = (expression) => {
563
- const testDiv = document.createElement('div');
564
- testDiv.innerHTML = expression;
565
- document.body.appendChild(testDiv);
566
-
567
- return typesetMathJax(testDiv)
568
- .then(success => {
569
- const result = {success, rendered: testDiv.innerHTML};
570
- document.body.removeChild(testDiv);
571
- return result;
572
- });
573
- };
574
  });
575
  </script>
576
  </body>
 
1
+
2
  <!DOCTYPE html>
3
  <html lang="fr">
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>Mariam M-0 | Solution Mathématique</title>
8
+ <!-- Tailwind CSS (version 2.2.19 utilisée ici, à mettre à jour si besoin) -->
9
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
10
 
11
+ <!-- Configuration optimisée de MathJax avec support étendu LaTeX -->
12
  <script>
13
  window.MathJax = {
14
  tex: {
15
+ inlineMath: [['$', '$']],
16
+ displayMath: [['$$', '$$']],
17
  processEscapes: true,
18
+ // Chargement automatique de commandes supplémentaires (ex. environnements de tableaux)
19
+ packages: {'[+]': ['autoload','ams']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  },
21
+
22
  options: {
23
+ enableMenu: false,
24
+ messageStyle: 'none'
 
 
 
 
 
 
25
  },
26
  startup: {
27
  pageReady: () => {
28
  console.log('MathJax est complètement chargé.');
29
  window.mathJaxReady = true;
 
30
  }
31
  }
32
  };
33
  </script>
34
+ <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" id="MathJax-script" async></script>
 
35
  <script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.min.js"></script>
36
 
37
  <style>
 
41
  font-family: 'Space Grotesk', sans-serif;
42
  }
43
 
 
44
  .uploadArea {
45
  background: #f3f4f6;
46
  border: 2px dashed #d1d5db;
 
100
  margin-left: 8px;
101
  }
102
 
103
+ /* Styles supplémentaires pour une meilleure présentation des tableaux */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  table {
105
  border-collapse: collapse;
106
  width: 100%;
107
+ margin-bottom: 1rem;
108
  }
109
  th, td {
110
  border: 1px solid #d1d5db;
111
+ padding: 0.5rem;
112
  text-align: left;
113
  }
114
  th {
115
  background-color: #f3f4f6;
116
  font-weight: 600;
117
  }
118
+ /* Pour un rendu responsive, ajouter éventuellement : */
119
+ .table-responsive {
120
+ overflow-x: auto;
 
121
  }
122
  </style>
123
  </head>
 
129
  </header>
130
 
131
  <main>
 
132
  <form id="problemForm" class="space-y-6" novalidate>
133
  <!-- Zone de dépôt et sélection d'image -->
134
  <div class="uploadArea p-8 text-center relative" aria-label="Zone de dépôt d'image">
 
174
  </div>
175
  <div class="border-t pt-6">
176
  <h3 class="text-xl font-bold text-gray-800 mb-4">Solution</h3>
177
+ <!-- Enveloppement d'éventuels tableaux dans une div responsive -->
178
  <div id="answerContent" class="text-gray-700 table-responsive"></div>
179
  </div>
180
  </section>
 
201
  let thoughtsBuffer = '';
202
  let answerBuffer = '';
203
  let currentMode = null;
204
+ let updateTimeout = null; // Variable pour le debounce des mises à jour
 
205
 
206
  // Mise à jour de l'affichage du temps écoulé
207
  const updateTimestamp = () => {
 
257
  handleFileSelect(e.dataTransfer.files[0]);
258
  });
259
 
260
+ // Fonction pour relancer le rendu MathJax dès que le contenu de la réponse est mis à jour
261
+ const typesetAnswerIfReady = async () => {
262
+ if (window.mathJaxReady) {
263
+ MathJax.startup.document.elements = [document.getElementById('answerContent')];
264
+ await MathJax.typesetPromise();
265
+ answerContent.scrollTop = answerContent.scrollHeight;
266
+ } else {
267
+ setTimeout(typesetAnswerIfReady, 200);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
  };
270
 
271
+ // Fonction pour déclencher la mise à jour de l'affichage
272
  const updateDisplay = async () => {
273
+ // Mise à jour du contenu via marked
274
+ thoughtsContent.innerHTML = marked.parse(thoughtsBuffer);
275
+ answerContent.innerHTML = marked.parse(answerBuffer);
276
+
277
+ // Lancer le rendu MathJax
278
+ await typesetAnswerIfReady();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  updateTimeout = null;
280
  };
281
 
282
  // Fonction pour planifier la mise à jour (dé-bounce)
283
  const scheduleUpdate = () => {
284
+ if (updateTimeout) return;
285
+ updateTimeout = setTimeout(updateDisplay, 200);
 
 
286
  };
287
 
288
+ // Configuration de marked avec support du mode GFM (pour les tableaux) et interprétation des sauts de ligne
289
  marked.setOptions({
290
  gfm: true,
291
+ breaks: true
 
 
292
  });
293
 
294
  // Soumission du formulaire
 
321
  body: formData
322
  });
323
 
 
 
 
 
324
  const reader = response.body.getReader();
325
  const decoder = new TextDecoder();
326
  let buffer = '';
 
328
  // Traitement d'un chunk de données
329
  const processChunk = async chunk => {
330
  buffer += decoder.decode(chunk, { stream: true });
331
+ const lines = buffer.split('\n\n');
332
+ buffer = lines.pop(); // Conserver la dernière ligne incomplète
 
 
 
 
 
 
 
 
 
 
333
 
334
  for (const line of lines) {
335
  if (!line.startsWith('data:')) continue;
336
+ const data = JSON.parse(line.slice(5));
 
337
 
338
+ if (data.mode) {
339
+ currentMode = data.mode;
340
+ loader.classList.add('hidden');
341
+ solutionSection.classList.remove('hidden');
342
+ }
343
+ if (data.content) {
344
+ if (currentMode === 'thinking') {
345
+ thoughtsBuffer += data.content;
346
+ } else if (currentMode === 'answering') {
347
+ answerBuffer += data.content;
 
348
  }
 
 
349
  }
350
  }
351
+ // Planifier la mise à jour dé-bouncée
 
352
  scheduleUpdate();
353
  };
354
 
 
356
  while (true) {
357
  const { done, value } = await reader.read();
358
  if (done) {
359
+ // Traitement du contenu restant dans le buffer
360
+ if (buffer) {
361
+ const data = JSON.parse(buffer.slice(5));
362
+ if (data.content) {
363
+ if (currentMode === 'thinking') {
364
+ thoughtsBuffer += data.content;
365
+ } else if (currentMode === 'answering') {
366
+ answerBuffer += data.content;
 
 
367
  }
 
 
368
  }
369
  }
370
+ scheduleUpdate();
 
 
 
 
 
 
371
  break;
372
  }
373
  await processChunk(value);
 
375
  stopTimer();
376
  } catch (error) {
377
  console.error('Erreur:', error);
378
+ alert('Une erreur est survenue.');
379
  loader.classList.add('hidden');
380
  stopTimer();
381
  }
382
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  });
384
  </script>
385
  </body>