Spaces:
Sleeping
Sleeping
Update templates/maj.html
Browse files- templates/maj.html +45 -74
templates/maj.html
CHANGED
|
@@ -6,7 +6,6 @@
|
|
| 6 |
<title>Math Solver - Version Gratuite (MathJax)</title>
|
| 7 |
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/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 |
-
<!-- REMOVED KaTeX CSS -->
|
| 10 |
<style>
|
| 11 |
:root {
|
| 12 |
--primary-color: #4a6fa5;
|
|
@@ -84,23 +83,19 @@
|
|
| 84 |
footer { text-align: center; padding: 30px 0 20px 0; color: #666; font-size: 0.9rem; border-top: 1px solid #eee; margin-top: 40px; }
|
| 85 |
|
| 86 |
#solutionOutput { margin-top: 30px; text-align: left; display: none; }
|
| 87 |
-
#solution { background: #fff; padding: 20px; border-radius: 8px; text-align: left; line-height: 1.8; font-size: 1rem; border: 1px solid #eee; margin-top: 15px; overflow-x: hidden;
|
| 88 |
|
| 89 |
-
/* Code Block Styling */
|
| 90 |
.code-section { margin: 20px 0; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
|
| 91 |
.code-header { background-color: #343a40; color: white; padding: 10px 15px; font-size: 0.9em; font-family: 'Courier New', monospace; }
|
| 92 |
.code-content { margin: 0; padding: 15px; background-color: var(--code-bg); color: #e6e6e6; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 0.9em; line-height: 1.5; }
|
| 93 |
.code-content pre, .code-content code { margin: 0; padding: 0; background: none; white-space: pre; }
|
| 94 |
|
| 95 |
-
/* Output Block Styling */
|
| 96 |
.output-section { background-color: var(--output-bg); padding: 15px; margin: 15px 0; border-radius: 8px; border: 1px solid #d6e0e2; color: #333; font-family: 'Courier New', monospace; font-size: 0.9em; white-space: pre-wrap; overflow-x: auto; box-shadow: inset 0 1px 3px rgba(0,0,0,0.05); }
|
| 97 |
|
| 98 |
-
/* Step Styling */
|
| 99 |
.step-section { margin: 20px 0; padding: 15px; background-color: #fdfdfd; border-left: 4px solid var(--accent-color); border-radius: 0 5px 5px 0; overflow-wrap: break-word; }
|
| 100 |
.step-section:first-child { margin-top: 0; }
|
| 101 |
.step-section:last-child { margin-bottom: 0; }
|
| 102 |
|
| 103 |
-
/* Indicator Styling */
|
| 104 |
.indicator { display: flex; align-items: center; padding: 12px 15px; margin: 15px 0; border-radius: 8px; font-size: 0.95rem; border: 1px solid transparent; }
|
| 105 |
.indicator.thinking-indicator { background-color: #e3f2fd; color: #1565c0; border-color: #bde0fe; }
|
| 106 |
.indicator.executing-indicator { background-color: #ede7f6; color: #5e35b1; border-color: #d1c4e9; }
|
|
@@ -108,27 +103,21 @@
|
|
| 108 |
.indicator i { margin-right: 10px; font-size: 1.1em; animation: pulse 1.5s infinite ease-in-out; }
|
| 109 |
@keyframes pulse { 0%, 100% { opacity: 0.7; } 50% { opacity: 1; } }
|
| 110 |
|
| 111 |
-
|
| 112 |
-
/* Ensure container allows for potential horizontal scrolling of large equations */
|
| 113 |
-
.mjx-chtml { /* Target MathJax CommonHTML output */
|
| 114 |
overflow-x: auto;
|
| 115 |
overflow-y: hidden;
|
| 116 |
}
|
| 117 |
-
/* Improve spacing for display math */
|
| 118 |
mjx-container[display="true"] {
|
| 119 |
display: block;
|
| 120 |
margin: 1em 0;
|
| 121 |
text-align: center;
|
| 122 |
}
|
| 123 |
-
/* Handle potential overflow within display math specifically */
|
| 124 |
mjx-container[display="true"] > .mjx-chtml {
|
| 125 |
overflow-x: auto;
|
| 126 |
overflow-y: hidden;
|
| 127 |
-
padding: 0.2em 0;
|
| 128 |
}
|
| 129 |
|
| 130 |
-
|
| 131 |
-
/* --- Responsive Design --- */
|
| 132 |
@media (max-width: 992px) { .container { max-width: 90%; } }
|
| 133 |
@media (max-width: 768px) {
|
| 134 |
.container { padding: 15px; }
|
|
@@ -149,48 +138,36 @@
|
|
| 149 |
.content-box { padding: 15px; }
|
| 150 |
#solution { padding: 15px; }
|
| 151 |
.code-header, .code-content, .output-section { font-size: 0.85em; }
|
| 152 |
-
/* Ensure MathJax equations can still scroll on small screens */
|
| 153 |
.mjx-chtml {
|
| 154 |
-
font-size: 0.95em;
|
| 155 |
}
|
| 156 |
}
|
| 157 |
</style>
|
| 158 |
|
| 159 |
-
<!-- MathJax Configuration -->
|
| 160 |
<script>
|
| 161 |
window.MathJax = {
|
| 162 |
tex: {
|
| 163 |
-
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
| 164 |
-
displayMath: [['$$', '$$'], ['\\[', '\\]']],
|
| 165 |
-
processEscapes: true,
|
| 166 |
-
tags: 'ams',
|
| 167 |
-
macros: {
|
| 168 |
-
// Define custom macros here if needed
|
| 169 |
-
// R: "\\mathbb{R}",
|
| 170 |
-
// C: "\\mathbb{C}"
|
| 171 |
-
}
|
| 172 |
},
|
| 173 |
chtml: {
|
| 174 |
-
matchFontHeight: true,
|
| 175 |
-
scale: 1.0
|
| 176 |
},
|
| 177 |
options: {
|
| 178 |
-
ignoreHtmlClass: 'tex2jax_ignore',
|
| 179 |
-
processHtmlClass: 'tex2jax_process',
|
| 180 |
-
skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
|
| 181 |
},
|
| 182 |
startup: {
|
| 183 |
-
// Don't automatically typeset on page load, we'll trigger it manually
|
| 184 |
typeset: false,
|
| 185 |
-
// pageReady: () => {
|
| 186 |
-
// console.log("MathJax is ready to process content.");
|
| 187 |
-
// }
|
| 188 |
}
|
| 189 |
};
|
| 190 |
</script>
|
| 191 |
-
<!-- Load MathJax -->
|
| 192 |
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
| 193 |
-
<!-- REMOVED KaTeX JS -->
|
| 194 |
|
| 195 |
</head>
|
| 196 |
<body>
|
|
@@ -237,17 +214,14 @@
|
|
| 237 |
<div id="solutionOutput" style="display: none;">
|
| 238 |
<h3>Solution Détaillée :</h3>
|
| 239 |
<div id="loadingIndicator" class="indicator" style="display: none;">
|
| 240 |
-
<!-- Content set by JS -->
|
| 241 |
</div>
|
| 242 |
<div id="solution">
|
| 243 |
-
<!-- Solution content will be injected here -->
|
| 244 |
</div>
|
| 245 |
<div id="mathjaxProcessingIndicator" class="indicator answering-indicator" style="display: none; margin-top: 10px;">
|
| 246 |
<i class="fas fa-magic indicator-icon"></i><span>Mise en forme des équations...</span>
|
| 247 |
</div>
|
| 248 |
</div>
|
| 249 |
|
| 250 |
-
|
| 251 |
<div class="upgrade-section">
|
| 252 |
<h2>Besoin de plus ?</h2>
|
| 253 |
<p>Passez à la version Pro pour des fonctionnalités avancées et des résolutions illimitées.</p>
|
|
@@ -260,7 +234,6 @@
|
|
| 260 |
</footer>
|
| 261 |
</div>
|
| 262 |
|
| 263 |
-
<!-- Dependencies: Highlight.js -->
|
| 264 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
|
| 265 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/python.min.js"></script>
|
| 266 |
|
|
@@ -289,7 +262,13 @@
|
|
| 289 |
uploadStatus.textContent = `Image sélectionnée : ${file.name}`;
|
| 290 |
solutionOutput.style.display = 'none';
|
| 291 |
solutionDiv.innerHTML = '';
|
| 292 |
-
mathjaxIndicator.style.display = 'none';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 293 |
}
|
| 294 |
reader.readAsDataURL(file);
|
| 295 |
} else {
|
|
@@ -301,18 +280,29 @@
|
|
| 301 |
});
|
| 302 |
|
| 303 |
solveButton.addEventListener('click', function() {
|
| 304 |
-
|
| 305 |
-
if (!imageInput.files[0]) {
|
| 306 |
alert("Veuillez d'abord sélectionner une image.");
|
| 307 |
return;
|
| 308 |
}
|
| 309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
solutionOutput.style.display = 'block';
|
| 311 |
loadingIndicator.style.display = 'flex';
|
| 312 |
loadingIndicator.className = 'indicator thinking-indicator';
|
| 313 |
loadingIndicator.innerHTML = '<i class="fas fa-brain indicator-icon"></i><span>Préparation de la requête...</span>';
|
| 314 |
solutionDiv.innerHTML = '';
|
| 315 |
-
mathjaxIndicator.style.display = 'none';
|
| 316 |
|
| 317 |
fetch('/solved', {
|
| 318 |
method: 'POST',
|
|
@@ -325,52 +315,39 @@
|
|
| 325 |
const reader = response.body.getReader();
|
| 326 |
const decoder = new TextDecoder();
|
| 327 |
let buffer = '';
|
| 328 |
-
// No need for accumulatedContent if rendering at the end
|
| 329 |
|
| 330 |
function processStream({ done, value }) {
|
| 331 |
if (done) {
|
| 332 |
loadingIndicator.style.display = 'none';
|
| 333 |
|
| 334 |
-
// Process any remaining buffer content
|
| 335 |
if (buffer.trim()) {
|
| 336 |
-
// Append the final chunk - assumes it's a regular step
|
| 337 |
const finalStepDiv = document.createElement('div');
|
| 338 |
finalStepDiv.className = 'step-section';
|
| 339 |
-
finalStepDiv.innerHTML = buffer;
|
| 340 |
solutionDiv.appendChild(finalStepDiv);
|
| 341 |
}
|
| 342 |
|
| 343 |
-
// --- Trigger MathJax Rendering ---
|
| 344 |
if (typeof MathJax !== 'undefined' && MathJax.typesetPromise) {
|
| 345 |
-
// Show MathJax processing indicator
|
| 346 |
mathjaxIndicator.style.display = 'flex';
|
| 347 |
-
|
| 348 |
-
MathJax.typesetPromise([solutionDiv]) // Target specific container
|
| 349 |
.then(() => {
|
| 350 |
-
|
| 351 |
-
mathjaxIndicator.style.display = 'none'; // Hide indicator on success
|
| 352 |
-
// Optional: Re-apply highlight.js if MathJax altered code blocks (unlikely but possible)
|
| 353 |
-
// document.querySelectorAll('#solution pre code').forEach((block) => {
|
| 354 |
-
// hljs.highlightElement(block);
|
| 355 |
-
// });
|
| 356 |
})
|
| 357 |
.catch((err) => {
|
| 358 |
console.error('Erreur de rendu MathJax:', err);
|
| 359 |
-
mathjaxIndicator.style.display = 'none';
|
| 360 |
solutionDiv.innerHTML += `<div style="color: orange; margin-top: 10px;">Erreur lors de l'affichage des formules mathématiques (MathJax).</div>`;
|
| 361 |
})
|
| 362 |
.finally(() => {
|
| 363 |
-
// Scroll to the solution area after rendering attempt
|
| 364 |
solutionOutput.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
| 365 |
});
|
| 366 |
} else {
|
| 367 |
console.warn("MathJax n'est pas prêt ou n'a pas pu être chargé.");
|
| 368 |
solutionDiv.innerHTML += `<div style="color: orange; margin-top: 10px;">Impossible de charger le module d'affichage mathématique (MathJax).</div>`;
|
| 369 |
-
// Scroll anyway
|
| 370 |
solutionOutput.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
| 371 |
}
|
| 372 |
-
return;
|
| 373 |
-
}
|
| 374 |
|
| 375 |
buffer += decoder.decode(value, { stream: true });
|
| 376 |
const parts = buffer.split('\n\n');
|
|
@@ -381,7 +358,6 @@
|
|
| 381 |
try {
|
| 382 |
const jsonData = JSON.parse(part.substring(6));
|
| 383 |
|
| 384 |
-
// Update Indicator (same as before)
|
| 385 |
if (jsonData.mode) {
|
| 386 |
loadingIndicator.style.display = 'flex';
|
| 387 |
if (jsonData.mode === 'thinking') {
|
|
@@ -399,7 +375,6 @@
|
|
| 399 |
}
|
| 400 |
}
|
| 401 |
|
| 402 |
-
// Append Content (same as before, but NO LaTeX rendering here)
|
| 403 |
if (jsonData.content) {
|
| 404 |
const content = jsonData.content;
|
| 405 |
let elementToAppend;
|
|
@@ -411,7 +386,7 @@
|
|
| 411 |
elementToAppend.innerHTML = `
|
| 412 |
<div class="code-header">Code Python</div>
|
| 413 |
<div class="code-content"><pre><code class="language-python tex2jax_ignore">${escapeHtml(code)}</code></pre></div>
|
| 414 |
-
`;
|
| 415 |
solutionDiv.appendChild(elementToAppend);
|
| 416 |
const codeBlock = elementToAppend.querySelector('code');
|
| 417 |
if (codeBlock && hljs) { hljs.highlightElement(codeBlock); }
|
|
@@ -419,15 +394,14 @@
|
|
| 419 |
} else if (content.startsWith('Résultat d\'exécution:\n```')) {
|
| 420 |
const output = content.replace(/^Résultat d'exécution:\n```\n?([\s\S]*?)\n?```$/, '$1');
|
| 421 |
elementToAppend = document.createElement('div');
|
| 422 |
-
elementToAppend.className = 'output-section tex2jax_ignore';
|
| 423 |
elementToAppend.textContent = output;
|
| 424 |
solutionDiv.appendChild(elementToAppend);
|
| 425 |
|
| 426 |
} else {
|
| 427 |
-
// Regular step, potentially with LaTeX delimiters inside
|
| 428 |
elementToAppend = document.createElement('div');
|
| 429 |
elementToAppend.className = 'step-section';
|
| 430 |
-
elementToAppend.innerHTML = content;
|
| 431 |
solutionDiv.appendChild(elementToAppend);
|
| 432 |
}
|
| 433 |
}
|
|
@@ -446,14 +420,11 @@
|
|
| 446 |
}
|
| 447 |
});
|
| 448 |
|
| 449 |
-
// Scroll down as content arrives
|
| 450 |
solutionDiv.lastChild?.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
| 451 |
|
| 452 |
-
// Continue reading the stream
|
| 453 |
return reader.read().then(processStream);
|
| 454 |
-
}
|
| 455 |
|
| 456 |
-
// Start processing the stream
|
| 457 |
return reader.read().then(processStream);
|
| 458 |
})
|
| 459 |
.catch(error => {
|
|
|
|
| 6 |
<title>Math Solver - Version Gratuite (MathJax)</title>
|
| 7 |
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/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;
|
|
|
|
| 83 |
footer { text-align: center; padding: 30px 0 20px 0; color: #666; font-size: 0.9rem; border-top: 1px solid #eee; margin-top: 40px; }
|
| 84 |
|
| 85 |
#solutionOutput { margin-top: 30px; text-align: left; display: none; }
|
| 86 |
+
#solution { background: #fff; padding: 20px; border-radius: 8px; text-align: left; line-height: 1.8; font-size: 1rem; border: 1px solid #eee; margin-top: 15px; overflow-x: hidden; }
|
| 87 |
|
|
|
|
| 88 |
.code-section { margin: 20px 0; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
|
| 89 |
.code-header { background-color: #343a40; color: white; padding: 10px 15px; font-size: 0.9em; font-family: 'Courier New', monospace; }
|
| 90 |
.code-content { margin: 0; padding: 15px; background-color: var(--code-bg); color: #e6e6e6; overflow-x: auto; font-family: 'Courier New', monospace; font-size: 0.9em; line-height: 1.5; }
|
| 91 |
.code-content pre, .code-content code { margin: 0; padding: 0; background: none; white-space: pre; }
|
| 92 |
|
|
|
|
| 93 |
.output-section { background-color: var(--output-bg); padding: 15px; margin: 15px 0; border-radius: 8px; border: 1px solid #d6e0e2; color: #333; font-family: 'Courier New', monospace; font-size: 0.9em; white-space: pre-wrap; overflow-x: auto; box-shadow: inset 0 1px 3px rgba(0,0,0,0.05); }
|
| 94 |
|
|
|
|
| 95 |
.step-section { margin: 20px 0; padding: 15px; background-color: #fdfdfd; border-left: 4px solid var(--accent-color); border-radius: 0 5px 5px 0; overflow-wrap: break-word; }
|
| 96 |
.step-section:first-child { margin-top: 0; }
|
| 97 |
.step-section:last-child { margin-bottom: 0; }
|
| 98 |
|
|
|
|
| 99 |
.indicator { display: flex; align-items: center; padding: 12px 15px; margin: 15px 0; border-radius: 8px; font-size: 0.95rem; border: 1px solid transparent; }
|
| 100 |
.indicator.thinking-indicator { background-color: #e3f2fd; color: #1565c0; border-color: #bde0fe; }
|
| 101 |
.indicator.executing-indicator { background-color: #ede7f6; color: #5e35b1; border-color: #d1c4e9; }
|
|
|
|
| 103 |
.indicator i { margin-right: 10px; font-size: 1.1em; animation: pulse 1.5s infinite ease-in-out; }
|
| 104 |
@keyframes pulse { 0%, 100% { opacity: 0.7; } 50% { opacity: 1; } }
|
| 105 |
|
| 106 |
+
.mjx-chtml {
|
|
|
|
|
|
|
| 107 |
overflow-x: auto;
|
| 108 |
overflow-y: hidden;
|
| 109 |
}
|
|
|
|
| 110 |
mjx-container[display="true"] {
|
| 111 |
display: block;
|
| 112 |
margin: 1em 0;
|
| 113 |
text-align: center;
|
| 114 |
}
|
|
|
|
| 115 |
mjx-container[display="true"] > .mjx-chtml {
|
| 116 |
overflow-x: auto;
|
| 117 |
overflow-y: hidden;
|
| 118 |
+
padding: 0.2em 0;
|
| 119 |
}
|
| 120 |
|
|
|
|
|
|
|
| 121 |
@media (max-width: 992px) { .container { max-width: 90%; } }
|
| 122 |
@media (max-width: 768px) {
|
| 123 |
.container { padding: 15px; }
|
|
|
|
| 138 |
.content-box { padding: 15px; }
|
| 139 |
#solution { padding: 15px; }
|
| 140 |
.code-header, .code-content, .output-section { font-size: 0.85em; }
|
|
|
|
| 141 |
.mjx-chtml {
|
| 142 |
+
font-size: 0.95em;
|
| 143 |
}
|
| 144 |
}
|
| 145 |
</style>
|
| 146 |
|
|
|
|
| 147 |
<script>
|
| 148 |
window.MathJax = {
|
| 149 |
tex: {
|
| 150 |
+
inlineMath: [['$', '$'], ['\\(', '\\)']],
|
| 151 |
+
displayMath: [['$$', '$$'], ['\\[', '\\]']],
|
| 152 |
+
processEscapes: true,
|
| 153 |
+
tags: 'ams',
|
| 154 |
+
macros: {}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
},
|
| 156 |
chtml: {
|
| 157 |
+
matchFontHeight: true,
|
| 158 |
+
scale: 1.0
|
| 159 |
},
|
| 160 |
options: {
|
| 161 |
+
ignoreHtmlClass: 'tex2jax_ignore',
|
| 162 |
+
processHtmlClass: 'tex2jax_process',
|
| 163 |
+
skipHtmlTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
|
| 164 |
},
|
| 165 |
startup: {
|
|
|
|
| 166 |
typeset: false,
|
|
|
|
|
|
|
|
|
|
| 167 |
}
|
| 168 |
};
|
| 169 |
</script>
|
|
|
|
| 170 |
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
|
|
|
| 171 |
|
| 172 |
</head>
|
| 173 |
<body>
|
|
|
|
| 214 |
<div id="solutionOutput" style="display: none;">
|
| 215 |
<h3>Solution Détaillée :</h3>
|
| 216 |
<div id="loadingIndicator" class="indicator" style="display: none;">
|
|
|
|
| 217 |
</div>
|
| 218 |
<div id="solution">
|
|
|
|
| 219 |
</div>
|
| 220 |
<div id="mathjaxProcessingIndicator" class="indicator answering-indicator" style="display: none; margin-top: 10px;">
|
| 221 |
<i class="fas fa-magic indicator-icon"></i><span>Mise en forme des équations...</span>
|
| 222 |
</div>
|
| 223 |
</div>
|
| 224 |
|
|
|
|
| 225 |
<div class="upgrade-section">
|
| 226 |
<h2>Besoin de plus ?</h2>
|
| 227 |
<p>Passez à la version Pro pour des fonctionnalités avancées et des résolutions illimitées.</p>
|
|
|
|
| 234 |
</footer>
|
| 235 |
</div>
|
| 236 |
|
|
|
|
| 237 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
|
| 238 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/python.min.js"></script>
|
| 239 |
|
|
|
|
| 262 |
uploadStatus.textContent = `Image sélectionnée : ${file.name}`;
|
| 263 |
solutionOutput.style.display = 'none';
|
| 264 |
solutionDiv.innerHTML = '';
|
| 265 |
+
mathjaxIndicator.style.display = 'none';
|
| 266 |
+
}
|
| 267 |
+
reader.onerror = function(e) {
|
| 268 |
+
console.error("FileReader error:", e);
|
| 269 |
+
uploadStatus.textContent = "Erreur lors de la lecture de l'image.";
|
| 270 |
+
imagePreview.style.display = 'none';
|
| 271 |
+
solveButton.style.display = 'none';
|
| 272 |
}
|
| 273 |
reader.readAsDataURL(file);
|
| 274 |
} else {
|
|
|
|
| 280 |
});
|
| 281 |
|
| 282 |
solveButton.addEventListener('click', function() {
|
| 283 |
+
if (!imageInput.files || imageInput.files.length === 0) {
|
|
|
|
| 284 |
alert("Veuillez d'abord sélectionner une image.");
|
| 285 |
return;
|
| 286 |
}
|
| 287 |
|
| 288 |
+
if (!imageForm) {
|
| 289 |
+
alert("Erreur interne: Le formulaire d'upload est introuvable.");
|
| 290 |
+
return;
|
| 291 |
+
}
|
| 292 |
+
const formData = new FormData(imageForm);
|
| 293 |
+
|
| 294 |
+
const fileData = formData.get('image');
|
| 295 |
+
if (!fileData || fileData.size === 0) {
|
| 296 |
+
alert("Erreur lors de la préparation de l'image pour l'envoi.");
|
| 297 |
+
return;
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
solutionOutput.style.display = 'block';
|
| 301 |
loadingIndicator.style.display = 'flex';
|
| 302 |
loadingIndicator.className = 'indicator thinking-indicator';
|
| 303 |
loadingIndicator.innerHTML = '<i class="fas fa-brain indicator-icon"></i><span>Préparation de la requête...</span>';
|
| 304 |
solutionDiv.innerHTML = '';
|
| 305 |
+
mathjaxIndicator.style.display = 'none';
|
| 306 |
|
| 307 |
fetch('/solved', {
|
| 308 |
method: 'POST',
|
|
|
|
| 315 |
const reader = response.body.getReader();
|
| 316 |
const decoder = new TextDecoder();
|
| 317 |
let buffer = '';
|
|
|
|
| 318 |
|
| 319 |
function processStream({ done, value }) {
|
| 320 |
if (done) {
|
| 321 |
loadingIndicator.style.display = 'none';
|
| 322 |
|
|
|
|
| 323 |
if (buffer.trim()) {
|
|
|
|
| 324 |
const finalStepDiv = document.createElement('div');
|
| 325 |
finalStepDiv.className = 'step-section';
|
| 326 |
+
finalStepDiv.innerHTML = buffer;
|
| 327 |
solutionDiv.appendChild(finalStepDiv);
|
| 328 |
}
|
| 329 |
|
|
|
|
| 330 |
if (typeof MathJax !== 'undefined' && MathJax.typesetPromise) {
|
|
|
|
| 331 |
mathjaxIndicator.style.display = 'flex';
|
| 332 |
+
MathJax.typesetPromise([solutionDiv])
|
|
|
|
| 333 |
.then(() => {
|
| 334 |
+
mathjaxIndicator.style.display = 'none';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
})
|
| 336 |
.catch((err) => {
|
| 337 |
console.error('Erreur de rendu MathJax:', err);
|
| 338 |
+
mathjaxIndicator.style.display = 'none';
|
| 339 |
solutionDiv.innerHTML += `<div style="color: orange; margin-top: 10px;">Erreur lors de l'affichage des formules mathématiques (MathJax).</div>`;
|
| 340 |
})
|
| 341 |
.finally(() => {
|
|
|
|
| 342 |
solutionOutput.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
| 343 |
});
|
| 344 |
} else {
|
| 345 |
console.warn("MathJax n'est pas prêt ou n'a pas pu être chargé.");
|
| 346 |
solutionDiv.innerHTML += `<div style="color: orange; margin-top: 10px;">Impossible de charger le module d'affichage mathématique (MathJax).</div>`;
|
|
|
|
| 347 |
solutionOutput.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
| 348 |
}
|
| 349 |
+
return;
|
| 350 |
+
}
|
| 351 |
|
| 352 |
buffer += decoder.decode(value, { stream: true });
|
| 353 |
const parts = buffer.split('\n\n');
|
|
|
|
| 358 |
try {
|
| 359 |
const jsonData = JSON.parse(part.substring(6));
|
| 360 |
|
|
|
|
| 361 |
if (jsonData.mode) {
|
| 362 |
loadingIndicator.style.display = 'flex';
|
| 363 |
if (jsonData.mode === 'thinking') {
|
|
|
|
| 375 |
}
|
| 376 |
}
|
| 377 |
|
|
|
|
| 378 |
if (jsonData.content) {
|
| 379 |
const content = jsonData.content;
|
| 380 |
let elementToAppend;
|
|
|
|
| 386 |
elementToAppend.innerHTML = `
|
| 387 |
<div class="code-header">Code Python</div>
|
| 388 |
<div class="code-content"><pre><code class="language-python tex2jax_ignore">${escapeHtml(code)}</code></pre></div>
|
| 389 |
+
`;
|
| 390 |
solutionDiv.appendChild(elementToAppend);
|
| 391 |
const codeBlock = elementToAppend.querySelector('code');
|
| 392 |
if (codeBlock && hljs) { hljs.highlightElement(codeBlock); }
|
|
|
|
| 394 |
} else if (content.startsWith('Résultat d\'exécution:\n```')) {
|
| 395 |
const output = content.replace(/^Résultat d'exécution:\n```\n?([\s\S]*?)\n?```$/, '$1');
|
| 396 |
elementToAppend = document.createElement('div');
|
| 397 |
+
elementToAppend.className = 'output-section tex2jax_ignore';
|
| 398 |
elementToAppend.textContent = output;
|
| 399 |
solutionDiv.appendChild(elementToAppend);
|
| 400 |
|
| 401 |
} else {
|
|
|
|
| 402 |
elementToAppend = document.createElement('div');
|
| 403 |
elementToAppend.className = 'step-section';
|
| 404 |
+
elementToAppend.innerHTML = content;
|
| 405 |
solutionDiv.appendChild(elementToAppend);
|
| 406 |
}
|
| 407 |
}
|
|
|
|
| 420 |
}
|
| 421 |
});
|
| 422 |
|
|
|
|
| 423 |
solutionDiv.lastChild?.scrollIntoView({ behavior: 'smooth', block: 'end' });
|
| 424 |
|
|
|
|
| 425 |
return reader.read().then(processStream);
|
| 426 |
+
}
|
| 427 |
|
|
|
|
| 428 |
return reader.read().then(processStream);
|
| 429 |
})
|
| 430 |
.catch(error => {
|