Docfile commited on
Commit
57e1e1f
·
verified ·
1 Parent(s): 5dd2816

Update templates/maj.html

Browse files
Files changed (1) hide show
  1. templates/maj.html +136 -213
templates/maj.html CHANGED
@@ -6,7 +6,6 @@
6
  <title>Math Solver - Version Gratuite</title>
7
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css" rel="stylesheet">
9
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min.css">
10
  <style>
11
  :root {
12
  --primary-color: #4a6fa5;
@@ -19,12 +18,6 @@
19
  --output-bg: #f1f8f9;
20
  }
21
 
22
- * {
23
- box-sizing: border-box;
24
- margin: 0;
25
- padding: 0;
26
- }
27
-
28
  body {
29
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
30
  line-height: 1.6;
@@ -35,7 +28,6 @@
35
  }
36
 
37
  .container {
38
- width: 100%;
39
  max-width: 1000px;
40
  margin: 0 auto;
41
  padding: 20px;
@@ -72,23 +64,12 @@
72
  h1 {
73
  color: var(--primary-color);
74
  margin-top: 0;
75
- margin-bottom: 1rem;
76
- }
77
-
78
- h2 {
79
- color: var(--secondary-color);
80
- margin: 1.5rem 0 1rem;
81
- }
82
-
83
- h3 {
84
- color: var(--secondary-color);
85
- margin: 1rem 0;
86
  }
87
 
88
  .feature-list {
89
  list-style-type: none;
90
  padding: 0;
91
- margin: 20px 0;
92
  text-align: left;
93
  }
94
 
@@ -103,7 +84,6 @@
103
  color: var(--accent-color);
104
  margin-right: 10px;
105
  font-size: 1.2rem;
106
- flex-shrink: 0;
107
  }
108
 
109
  .cta-button {
@@ -146,7 +126,6 @@
146
  text-align: left;
147
  line-height: 1.8;
148
  font-size: 16px;
149
- overflow-x: auto;
150
  }
151
 
152
  .code-section {
@@ -167,8 +146,7 @@
167
  align-items: center;
168
  }
169
 
170
- .code-content,
171
- pre code {
172
  margin: 0;
173
  padding: 15px;
174
  background-color: var(--code-bg);
@@ -177,7 +155,6 @@
177
  font-family: 'Courier New', monospace;
178
  font-size: 14px;
179
  line-height: 1.5;
180
- width: 100%;
181
  }
182
 
183
  .output-section {
@@ -198,18 +175,17 @@
198
  background-color: #f9f9f9;
199
  border-left: 4px solid var(--primary-color);
200
  border-radius: 0 8px 8px 0;
201
- overflow-x: auto;
202
  }
203
 
204
- .math-display {
205
  overflow-x: auto;
206
  padding: 10px 0;
 
207
  text-align: center;
208
  }
209
 
210
- .thinking-indicator,
211
- .executing-indicator,
212
- .answering-indicator {
213
  display: flex;
214
  align-items: center;
215
  padding: 10px;
@@ -244,110 +220,34 @@
244
  100% { opacity: 0.6; }
245
  }
246
 
247
- .katex-display {
248
- overflow-x: auto;
249
- padding: 8px 0;
 
 
250
  }
251
 
252
- #imagePreview {
253
- max-width: 100%;
254
- margin: 20px auto;
 
255
  }
256
 
257
- #preview {
258
- max-width: 100%;
259
- height: auto;
260
- border-radius: 8px;
261
- box-shadow: var(--box-shadow);
 
262
  }
263
 
264
- #uploadStatus {
265
- margin: 10px 0;
266
- font-size: 0.9rem;
267
- color: #666;
268
- }
269
-
270
- /* Responsive design adjustments */
271
  @media (max-width: 768px) {
272
  .container {
273
- padding: 10px;
274
- }
275
-
276
- .content-box {
277
  padding: 15px;
278
- margin-bottom: 20px;
279
- }
280
-
281
- .logo {
282
- font-size: 2rem;
283
- }
284
-
285
- .subtitle {
286
- font-size: 1rem;
287
- }
288
-
289
- .cta-button {
290
- padding: 10px 20px;
291
- font-size: 0.9rem;
292
- margin: 15px 5px;
293
- width: 100%;
294
- max-width: 300px;
295
- }
296
-
297
- h1 {
298
- font-size: 1.8rem;
299
- }
300
-
301
- h2 {
302
- font-size: 1.4rem;
303
- }
304
-
305
- .feature-list li {
306
- padding: 8px 0;
307
- }
308
-
309
- #solution {
310
- padding: 15px;
311
- font-size: 15px;
312
- }
313
-
314
- .step-section {
315
- padding: 12px;
316
- margin: 20px 0;
317
- }
318
- }
319
-
320
- @media (max-width: 480px) {
321
- .logo {
322
- font-size: 1.8rem;
323
- }
324
-
325
- .subtitle {
326
- font-size: 0.9rem;
327
- }
328
-
329
- h1 {
330
- font-size: 1.6rem;
331
- }
332
-
333
- h2 {
334
- font-size: 1.3rem;
335
  }
336
 
337
  .content-box {
338
- padding: 12px;
339
- }
340
-
341
- .cta-button {
342
- padding: 8px 16px;
343
- font-size: 0.85rem;
344
- }
345
-
346
- #solution,
347
- .code-content,
348
- pre code,
349
- .output-section {
350
- font-size: 13px;
351
  }
352
  }
353
  </style>
@@ -363,7 +263,7 @@
363
  <h1>Version Gratuite</h1>
364
  <p>Vous utilisez actuellement la version gratuite de Math Solver qui vous permet de résoudre 3 problèmes par jour.</p>
365
 
366
- <div>
367
  <h2>Fonctionnalités disponibles :</h2>
368
  <ul class="feature-list">
369
  <li><i class="fas fa-check-circle"></i> Résolution de problèmes mathématiques basiques</li>
@@ -384,8 +284,8 @@
384
  </form>
385
 
386
  <p id="uploadStatus"></p>
387
- <div id="imagePreview" style="display: none;">
388
- <img id="preview" style="width: 100%;">
389
  </div>
390
 
391
  <button id="solveButton" class="cta-button" style="display: none; background-color: var(--secondary-color);">
@@ -399,7 +299,7 @@
399
  <i class="fas fa-brain indicator-icon"></i>
400
  <span>Je réfléchis au problème...</span>
401
  </div>
402
- <div id="solution"></div>
403
  </div>
404
 
405
  <div class="upgrade-section">
@@ -416,52 +316,69 @@
416
 
417
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
418
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/python.min.js"></script>
419
- <script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min.js"></script>
420
- <script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/contrib/auto-render.min.js"></script>
421
 
 
422
  <script>
423
- // Configuration globale pour KaTeX
424
- document.addEventListener("DOMContentLoaded", function() {
425
- // Définir les options pour renderMathInElement
426
- window.renderMathConfig = {
427
- delimiters: [
428
- {left: '$$', right: '$$', display: true},
429
- {left: '$', right: '$', display: false},
430
- {left: '\\(', right: '\\)', display: false},
431
- {left: '\\[', right: '\\]', display: true},
432
- {left: '\\begin{equation}', right: '\\end{equation}', display: true},
433
- {left: '\\begin{align}', right: '\\end{align}', display: true},
434
- {left: '\\begin{alignat}', right: '\\end{alignat}', display: true},
435
- {left: '\\begin{gather}', right: '\\end{gather}', display: true},
436
- {left: '\\begin{CD}', right: '\\end{CD}', display: true}
437
- ],
438
- throwOnError: false,
439
- strict: false,
440
- trust: true,
441
- macros: {
442
- "\\R": "\\mathbb{R}",
443
- "\\N": "\\mathbb{N}",
444
- "\\Z": "\\mathbb{Z}",
445
- "\\Q": "\\mathbb{Q}",
446
- "\\C": "\\mathbb{C}"
447
  }
448
- };
449
- });
450
-
451
- // Fonction pour rendre LaTeX
452
- function renderLatex(element) {
453
- if (typeof renderMathInElement === 'function') {
454
- try {
455
- renderMathInElement(element, window.renderMathConfig);
456
- } catch (e) {
457
- console.error('Erreur lors du rendu LaTeX:', e);
458
- }
459
- } else {
460
- console.warn('La fonction renderMathInElement n\'est pas disponible');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
461
  }
 
 
 
 
 
 
 
 
462
  }
463
-
464
- // Gestion de l'upload d'image
465
  document.getElementById('imageInput').addEventListener('change', function(event) {
466
  const file = event.target.files[0];
467
  if (file) {
@@ -476,7 +393,6 @@
476
  }
477
  });
478
 
479
- // Fonction pour résoudre le problème
480
  document.getElementById('solveButton').addEventListener('click', function() {
481
  const formData = new FormData(document.getElementById('imageForm'));
482
  const solutionOutput = document.getElementById('solutionOutput');
@@ -487,8 +403,10 @@
487
  loadingIndicator.style.display = 'flex';
488
  solution.innerHTML = '';
489
 
490
- // Simuler un streaming pour l'exemple
491
- // Dans un environnement réel, ceci serait remplacé par un vrai appel fetch
 
 
492
  fetch('/solved', {
493
  method: 'POST',
494
  body: formData
@@ -501,21 +419,25 @@
501
  function processStream({ done, value }) {
502
  if (done) {
503
  loadingIndicator.style.display = 'none';
504
- // Rendu final de LaTeX
505
- renderLatex(solution);
 
 
 
 
 
506
  return;
507
  }
508
 
509
  buffer += decoder.decode(value, { stream: true });
510
  const lines = buffer.split('\n\n');
511
- buffer = lines.pop(); // Garder le morceau incomplet pour la prochaine fois
512
 
513
  for (const line of lines) {
514
  if (line.startsWith('data: ')) {
515
  try {
516
  const data = JSON.parse(line.substr(6));
517
 
518
- // Mettre à jour l'indicateur
519
  if (data.mode === 'thinking') {
520
  loadingIndicator.className = 'thinking-indicator';
521
  loadingIndicator.innerHTML = '<i class="fas fa-brain indicator-icon"></i><span>Je réfléchis au problème...</span>';
@@ -530,59 +452,69 @@
530
  loadingIndicator.innerHTML = '<i class="fas fa-terminal indicator-icon"></i><span>Traitement des résultats...</span>';
531
  }
532
 
533
- // Traiter le contenu
534
  if (data.content) {
535
  const content = data.content;
536
 
537
- // Détecter si c'est du code ou une sortie et formater en conséquence
 
 
 
538
  if (content.includes('```python')) {
539
- // C'est du code
540
- const code = content.replace(/```python\n([\s\S]*?)\n```/g, function(match, p1) {
541
  return `<div class="code-section">
542
  <div class="code-header">
543
  <span>Code Python</span>
544
  </div>
545
- <pre><code class="language-python">${p1}</code></pre>
546
  </div>`;
547
  });
548
- solution.innerHTML += code;
 
549
 
550
- // Appliquer la coloration syntaxique
551
- document.querySelectorAll('pre code').forEach((block) => {
552
  hljs.highlightElement(block);
553
  });
554
  }
555
  else if (content.includes('Résultat d\'exécution:')) {
556
- // C'est une sortie de code
557
- const output = content.replace(/Résultat d'exécution:\n```\n([\s\S]*?)\n```/g, function(match, p1) {
558
  return `<div class="output-section">${p1}</div>`;
559
  });
560
- solution.innerHTML += output;
 
561
  }
562
  else {
563
- // Texte normal, peut contenir du LaTeX
564
- solution.innerHTML += `<div class="step-section">${content}</div>`;
 
 
565
 
566
- // Rendu LaTeX incrémental
567
- renderLatex(solution.lastElementChild);
568
  }
569
  }
570
 
571
  if (data.error) {
572
- solution.innerHTML += `<div style="color: red; margin: 15px 0; padding: 10px; background: #ffeeee; border-radius: 5px;">Erreur: ${data.error}</div>`;
 
 
 
 
 
 
 
573
  loadingIndicator.style.display = 'none';
574
  }
575
  } catch (e) {
576
- console.error('Erreur d\'analyse JSON:', e, line);
577
  }
578
  }
579
  }
580
 
581
- // Défiler automatiquement vers le bas
582
- window.scrollTo({
583
- top: document.body.scrollHeight,
584
- behavior: 'smooth'
585
- });
586
 
587
  return reader.read().then(processStream);
588
  }
@@ -590,26 +522,17 @@
590
  return reader.read().then(processStream);
591
  })
592
  .catch(error => {
593
- solution.innerHTML += `<div style="color: red; margin: 15px 0; padding: 10px; background: #ffeeee; border-radius: 5px;">Erreur de connexion: ${error}</div>`;
 
 
 
 
 
 
 
594
  loadingIndicator.style.display = 'none';
595
  });
596
  });
597
-
598
- // Vérifier si les appareils sont de petite taille pour adapter l'interface
599
- function checkMobileDevice() {
600
- if (window.innerWidth <= 768) {
601
- // Ajustements spécifiques pour mobile si nécessaire
602
- const buttons = document.querySelectorAll('.cta-button');
603
- buttons.forEach(button => {
604
- button.style.display = 'block';
605
- button.style.margin = '15px auto';
606
- });
607
- }
608
- }
609
-
610
- // Exécuter au chargement et lors du redimensionnement
611
- window.addEventListener('load', checkMobileDevice);
612
- window.addEventListener('resize', checkMobileDevice);
613
  </script>
614
  </body>
615
  </html>
 
6
  <title>Math Solver - Version Gratuite</title>
7
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
8
  <link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css" rel="stylesheet">
 
9
  <style>
10
  :root {
11
  --primary-color: #4a6fa5;
 
18
  --output-bg: #f1f8f9;
19
  }
20
 
 
 
 
 
 
 
21
  body {
22
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
23
  line-height: 1.6;
 
28
  }
29
 
30
  .container {
 
31
  max-width: 1000px;
32
  margin: 0 auto;
33
  padding: 20px;
 
64
  h1 {
65
  color: var(--primary-color);
66
  margin-top: 0;
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
 
69
  .feature-list {
70
  list-style-type: none;
71
  padding: 0;
72
+ margin: 30px 0;
73
  text-align: left;
74
  }
75
 
 
84
  color: var(--accent-color);
85
  margin-right: 10px;
86
  font-size: 1.2rem;
 
87
  }
88
 
89
  .cta-button {
 
126
  text-align: left;
127
  line-height: 1.8;
128
  font-size: 16px;
 
129
  }
130
 
131
  .code-section {
 
146
  align-items: center;
147
  }
148
 
149
+ .code-content {
 
150
  margin: 0;
151
  padding: 15px;
152
  background-color: var(--code-bg);
 
155
  font-family: 'Courier New', monospace;
156
  font-size: 14px;
157
  line-height: 1.5;
 
158
  }
159
 
160
  .output-section {
 
175
  background-color: #f9f9f9;
176
  border-left: 4px solid var(--primary-color);
177
  border-radius: 0 8px 8px 0;
178
+ overflow-x: auto; /* Pour les formules LaTeX larges */
179
  }
180
 
181
+ .latex-display {
182
  overflow-x: auto;
183
  padding: 10px 0;
184
+ margin: 15px 0;
185
  text-align: center;
186
  }
187
 
188
+ .thinking-indicator, .executing-indicator, .answering-indicator {
 
 
189
  display: flex;
190
  align-items: center;
191
  padding: 10px;
 
220
  100% { opacity: 0.6; }
221
  }
222
 
223
+ /* Styles spécifiques à MathJax */
224
+ .MathJax {
225
+ overflow-x: auto !important;
226
+ overflow-y: hidden !important;
227
+ max-width: 100% !important;
228
  }
229
 
230
+ .mjx-chtml {
231
+ overflow-x: auto !important;
232
+ overflow-y: hidden !important;
233
+ max-width: 100% !important;
234
  }
235
 
236
+ mjx-container {
237
+ overflow-x: auto !important;
238
+ overflow-y: hidden !important;
239
+ max-width: 100% !important;
240
+ min-width: 0 !important;
241
+ padding: 2px 0;
242
  }
243
 
 
 
 
 
 
 
 
244
  @media (max-width: 768px) {
245
  .container {
 
 
 
 
246
  padding: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
247
  }
248
 
249
  .content-box {
250
+ padding: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
251
  }
252
  }
253
  </style>
 
263
  <h1>Version Gratuite</h1>
264
  <p>Vous utilisez actuellement la version gratuite de Math Solver qui vous permet de résoudre 3 problèmes par jour.</p>
265
 
266
+ <div class="feature-list">
267
  <h2>Fonctionnalités disponibles :</h2>
268
  <ul class="feature-list">
269
  <li><i class="fas fa-check-circle"></i> Résolution de problèmes mathématiques basiques</li>
 
284
  </form>
285
 
286
  <p id="uploadStatus"></p>
287
+ <div id="imagePreview" style="display: none; margin: 20px auto; max-width: 500px;">
288
+ <img id="preview" style="width: 100%; border-radius: 8px; box-shadow: var(--box-shadow);">
289
  </div>
290
 
291
  <button id="solveButton" class="cta-button" style="display: none; background-color: var(--secondary-color);">
 
299
  <i class="fas fa-brain indicator-icon"></i>
300
  <span>Je réfléchis au problème...</span>
301
  </div>
302
+ <div id="solution" style="background: #fff; padding: 20px; border-radius: 8px;"></div>
303
  </div>
304
 
305
  <div class="upgrade-section">
 
316
 
317
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
318
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/python.min.js"></script>
 
 
319
 
320
+ <!-- MathJax Configuration -->
321
  <script>
322
+ window.MathJax = {
323
+ tex: {
324
+ inlineMath: [['$', '$'], ['\\(', '\\)']],
325
+ displayMath: [['$$', '$$'], ['\\[', '\\]']],
326
+ processEscapes: true,
327
+ processEnvironments: true,
328
+ packages: {'[+]': ['ams', 'noerrors', 'physics', 'cancel', 'color', 'mhchem', 'mathtools']}
329
+ },
330
+ options: {
331
+ enableMenu: false,
332
+ renderActions: {
333
+ addMenu: [], // Disable menu
334
+ checkLoading: []
335
+ },
336
+ ignoreHtmlClass: 'code-content',
337
+ processHtmlClass: 'step-section|latex-display',
338
+ skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
339
+ },
340
+ startup: {
341
+ pageReady: function() {
342
+ return MathJax.startup.defaultPageReady();
 
 
 
343
  }
344
+ },
345
+ loader: {
346
+ load: ['[tex]/ams', '[tex]/noerrors', '[tex]/physics', '[tex]/cancel', '[tex]/color', '[tex]/mhchem', '[tex]/mathtools']
347
+ },
348
+ svg: {
349
+ fontCache: 'global'
350
+ }
351
+ };
352
+ </script>
353
+ <script id="MathJax-script" async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-svg.js"></script>
354
+
355
+ <script>
356
+ // Variables to manage MathJax rendering state
357
+ let mathJaxQueue = [];
358
+ let isProcessingMathQueue = false;
359
+
360
+ // Process MathJax queue with delay to avoid blocking UI
361
+ async function processMathJaxQueue() {
362
+ if (isProcessingMathQueue || mathJaxQueue.length === 0) return;
363
+
364
+ isProcessingMathQueue = true;
365
+ const element = mathJaxQueue.shift();
366
+
367
+ try {
368
+ await MathJax.typesetPromise([element]);
369
+ } catch (e) {
370
+ console.error('MathJax typesetting failed:', e);
371
  }
372
+
373
+ isProcessingMathQueue = false;
374
+ setTimeout(processMathJaxQueue, 100); // Small delay to allow UI updates
375
+ }
376
+
377
+ function addToMathJaxQueue(element) {
378
+ mathJaxQueue.push(element);
379
+ processMathJaxQueue();
380
  }
381
+
 
382
  document.getElementById('imageInput').addEventListener('change', function(event) {
383
  const file = event.target.files[0];
384
  if (file) {
 
393
  }
394
  });
395
 
 
396
  document.getElementById('solveButton').addEventListener('click', function() {
397
  const formData = new FormData(document.getElementById('imageForm'));
398
  const solutionOutput = document.getElementById('solutionOutput');
 
403
  loadingIndicator.style.display = 'flex';
404
  solution.innerHTML = '';
405
 
406
+ // Reset MathJax queue
407
+ mathJaxQueue = [];
408
+ isProcessingMathQueue = false;
409
+
410
  fetch('/solved', {
411
  method: 'POST',
412
  body: formData
 
419
  function processStream({ done, value }) {
420
  if (done) {
421
  loadingIndicator.style.display = 'none';
422
+
423
+ // Final MathJax render at the end
424
+ try {
425
+ addToMathJaxQueue(solution);
426
+ } catch (e) {
427
+ console.error('Error in final MathJax rendering:', e);
428
+ }
429
  return;
430
  }
431
 
432
  buffer += decoder.decode(value, { stream: true });
433
  const lines = buffer.split('\n\n');
434
+ buffer = lines.pop(); // Keep the incomplete chunk for next time
435
 
436
  for (const line of lines) {
437
  if (line.startsWith('data: ')) {
438
  try {
439
  const data = JSON.parse(line.substr(6));
440
 
 
441
  if (data.mode === 'thinking') {
442
  loadingIndicator.className = 'thinking-indicator';
443
  loadingIndicator.innerHTML = '<i class="fas fa-brain indicator-icon"></i><span>Je réfléchis au problème...</span>';
 
452
  loadingIndicator.innerHTML = '<i class="fas fa-terminal indicator-icon"></i><span>Traitement des résultats...</span>';
453
  }
454
 
 
455
  if (data.content) {
456
  const content = data.content;
457
 
458
+ // Create a container for this new content
459
+ const contentContainer = document.createElement('div');
460
+
461
+ // Detect if this is code or output and format appropriately
462
  if (content.includes('```python')) {
463
+ // This is code
464
+ const codeHtml = content.replace(/```python\n([\s\S]*?)\n```/g, function(match, p1) {
465
  return `<div class="code-section">
466
  <div class="code-header">
467
  <span>Code Python</span>
468
  </div>
469
+ <pre class="code-content"><code class="language-python">${p1}</code></pre>
470
  </div>`;
471
  });
472
+ contentContainer.innerHTML = codeHtml;
473
+ solution.appendChild(contentContainer);
474
 
475
+ // Apply syntax highlighting
476
+ contentContainer.querySelectorAll('pre code').forEach((block) => {
477
  hljs.highlightElement(block);
478
  });
479
  }
480
  else if (content.includes('Résultat d\'exécution:')) {
481
+ // This is code output
482
+ const outputHtml = content.replace(/Résultat d'exécution:\n```\n([\s\S]*?)\n```/g, function(match, p1) {
483
  return `<div class="output-section">${p1}</div>`;
484
  });
485
+ contentContainer.innerHTML = outputHtml;
486
+ solution.appendChild(contentContainer);
487
  }
488
  else {
489
+ // Regular text, might contain LaTeX
490
+ contentContainer.className = 'step-section';
491
+ contentContainer.innerHTML = content;
492
+ solution.appendChild(contentContainer);
493
 
494
+ // Add to MathJax rendering queue
495
+ addToMathJaxQueue(contentContainer);
496
  }
497
  }
498
 
499
  if (data.error) {
500
+ const errorDiv = document.createElement('div');
501
+ errorDiv.style.color = 'red';
502
+ errorDiv.style.margin = '15px 0';
503
+ errorDiv.style.padding = '10px';
504
+ errorDiv.style.background = '#ffeeee';
505
+ errorDiv.style.borderRadius = '5px';
506
+ errorDiv.textContent = `Erreur: ${data.error}`;
507
+ solution.appendChild(errorDiv);
508
  loadingIndicator.style.display = 'none';
509
  }
510
  } catch (e) {
511
+ console.error('Error parsing JSON:', e, line);
512
  }
513
  }
514
  }
515
 
516
+ // Scroll to bottom automatically
517
+ window.scrollTo(0, document.body.scrollHeight);
 
 
 
518
 
519
  return reader.read().then(processStream);
520
  }
 
522
  return reader.read().then(processStream);
523
  })
524
  .catch(error => {
525
+ const errorDiv = document.createElement('div');
526
+ errorDiv.style.color = 'red';
527
+ errorDiv.style.margin = '15px 0';
528
+ errorDiv.style.padding = '10px';
529
+ errorDiv.style.background = '#ffeeee';
530
+ errorDiv.style.borderRadius = '5px';
531
+ errorDiv.textContent = `Erreur de connexion: ${error}`;
532
+ solution.appendChild(errorDiv);
533
  loadingIndicator.style.display = 'none';
534
  });
535
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
536
  </script>
537
  </body>
538
  </html>