Spaces:
Running
Running
Upload index.html
Browse files- templates/index.html +11 -64
templates/index.html
CHANGED
@@ -1,3 +1,5 @@
|
|
|
|
|
|
1 |
<!DOCTYPE html>
|
2 |
<html lang="fr">
|
3 |
<head>
|
@@ -87,7 +89,7 @@
|
|
87 |
th { background-color: #f3f4f6; font-weight: 600; }
|
88 |
.table-responsive { overflow-x: auto; }
|
89 |
|
90 |
-
/* Style pour le bouton Sauvegarder */
|
91 |
#saveButton {
|
92 |
background: #3b82f6;
|
93 |
color: white;
|
@@ -169,7 +171,7 @@
|
|
169 |
<div class="border-t pt-6">
|
170 |
<div class="flex justify-between items-center">
|
171 |
<h3 class="text-xl font-bold text-gray-800 mb-4">Solution</h3>
|
172 |
-
<!-- Bouton Sauvegarder -->
|
173 |
<button id="saveButton">Sauvegarder</button>
|
174 |
</div>
|
175 |
<div id="answerContent" class="text-gray-700 table-responsive"></div>
|
@@ -218,6 +220,7 @@
|
|
218 |
const savedModal = document.getElementById('savedModal');
|
219 |
const savedList = document.getElementById('savedList');
|
220 |
const newExercise = document.getElementById('newExercise');
|
|
|
221 |
|
222 |
let startTime = null;
|
223 |
let timerInterval = null;
|
@@ -256,74 +259,17 @@
|
|
256 |
dropZone.addEventListener('dragleave', e => { e.preventDefault(); dropZone.classList.remove('border-blue-400'); });
|
257 |
dropZone.addEventListener('drop', e => { e.preventDefault(); dropZone.classList.remove('border-blue-400'); handleFileSelect(e.dataTransfer.files[0]); });
|
258 |
|
259 |
-
/*
|
260 |
-
Fonction améliorée de pré-traitement pour envelopper automatiquement
|
261 |
-
les commandes LaTeX dans des délimiteurs $...$.
|
262 |
-
Cette fonction parcourt le texte caractère par caractère, en tenant compte
|
263 |
-
du mode mathématique (délimité par $) pour éviter de retraiter du contenu déjà formaté.
|
264 |
-
*/
|
265 |
-
function autoWrapMath(text) {
|
266 |
-
let result = "";
|
267 |
-
let i = 0;
|
268 |
-
let inMath = false;
|
269 |
-
while(i < text.length) {
|
270 |
-
if (text[i] === '$') {
|
271 |
-
result += '$';
|
272 |
-
inMath = !inMath;
|
273 |
-
i++;
|
274 |
-
} else if (!inMath && text[i] === '\\') {
|
275 |
-
// On est hors du mode math, on traite la commande LaTeX
|
276 |
-
let start = i;
|
277 |
-
i++; // On saute le backslash
|
278 |
-
// Lecture du nom de la commande (lettres uniquement)
|
279 |
-
while(i < text.length && /[a-zA-Z]/.test(text[i])) { i++; }
|
280 |
-
// Gestion d'un argument optionnel éventuel : [ ... ]
|
281 |
-
if(i < text.length && text[i] === '[') {
|
282 |
-
let bracketCount = 0;
|
283 |
-
while(i < text.length) {
|
284 |
-
if(text[i] === '[') { bracketCount++; }
|
285 |
-
else if(text[i] === ']') { bracketCount--; }
|
286 |
-
i++;
|
287 |
-
if(bracketCount === 0) break;
|
288 |
-
}
|
289 |
-
}
|
290 |
-
// Gestion d'un ou plusieurs arguments obligatoires : { ... }
|
291 |
-
while(i < text.length && text[i] === '{') {
|
292 |
-
let braceCount = 0;
|
293 |
-
while(i < text.length) {
|
294 |
-
if(text[i] === '{') { braceCount++; }
|
295 |
-
else if(text[i] === '}') { braceCount--; }
|
296 |
-
i++;
|
297 |
-
if(braceCount === 0) break;
|
298 |
-
}
|
299 |
-
}
|
300 |
-
let commandStr = text.substring(start, i);
|
301 |
-
// On enveloppe la commande complète dans des délimiteurs $...$
|
302 |
-
result += '$' + commandStr + '$';
|
303 |
-
} else {
|
304 |
-
result += text[i];
|
305 |
-
i++;
|
306 |
-
}
|
307 |
-
}
|
308 |
-
return result;
|
309 |
-
}
|
310 |
-
|
311 |
// Rendu MathJax et mise à jour de l'affichage
|
312 |
const typesetAnswerIfReady = async () => {
|
313 |
if (window.mathJaxReady) {
|
314 |
MathJax.startup.document.elements = [document.getElementById('answerContent')];
|
315 |
await MathJax.typesetPromise();
|
316 |
answerContent.scrollTop = answerContent.scrollHeight;
|
317 |
-
} else {
|
318 |
-
setTimeout(typesetAnswerIfReady, 200);
|
319 |
-
}
|
320 |
};
|
321 |
const updateDisplay = async () => {
|
322 |
-
|
323 |
-
|
324 |
-
const processedAnswer = autoWrapMath(answerBuffer);
|
325 |
-
thoughtsContent.innerHTML = marked.parse(processedThoughts);
|
326 |
-
answerContent.innerHTML = marked.parse(processedAnswer);
|
327 |
await typesetAnswerIfReady();
|
328 |
updateTimeout = null;
|
329 |
};
|
@@ -448,7 +394,7 @@
|
|
448 |
openSaved.addEventListener('click', () => { loadSavedList(); savedModal.classList.add('active'); });
|
449 |
closeSaved.addEventListener('click', () => { savedModal.classList.remove('active'); });
|
450 |
|
451 |
-
// Bouton dans le modal pour lancer un nouvel exercice
|
452 |
newExercise.addEventListener('click', () => {
|
453 |
form.reset();
|
454 |
form.classList.remove('hidden');
|
@@ -463,4 +409,5 @@
|
|
463 |
});
|
464 |
</script>
|
465 |
</body>
|
466 |
-
</html>
|
|
|
|
1 |
+
|
2 |
+
|
3 |
<!DOCTYPE html>
|
4 |
<html lang="fr">
|
5 |
<head>
|
|
|
89 |
th { background-color: #f3f4f6; font-weight: 600; }
|
90 |
.table-responsive { overflow-x: auto; }
|
91 |
|
92 |
+
/* Style pour le bouton Sauvegarder afin de le mettre en évidence */
|
93 |
#saveButton {
|
94 |
background: #3b82f6;
|
95 |
color: white;
|
|
|
171 |
<div class="border-t pt-6">
|
172 |
<div class="flex justify-between items-center">
|
173 |
<h3 class="text-xl font-bold text-gray-800 mb-4">Solution</h3>
|
174 |
+
<!-- Bouton Sauvegarder mis en évidence -->
|
175 |
<button id="saveButton">Sauvegarder</button>
|
176 |
</div>
|
177 |
<div id="answerContent" class="text-gray-700 table-responsive"></div>
|
|
|
220 |
const savedModal = document.getElementById('savedModal');
|
221 |
const savedList = document.getElementById('savedList');
|
222 |
const newExercise = document.getElementById('newExercise');
|
223 |
+
const mainContent = document.getElementById('mainContent');
|
224 |
|
225 |
let startTime = null;
|
226 |
let timerInterval = null;
|
|
|
259 |
dropZone.addEventListener('dragleave', e => { e.preventDefault(); dropZone.classList.remove('border-blue-400'); });
|
260 |
dropZone.addEventListener('drop', e => { e.preventDefault(); dropZone.classList.remove('border-blue-400'); handleFileSelect(e.dataTransfer.files[0]); });
|
261 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
262 |
// Rendu MathJax et mise à jour de l'affichage
|
263 |
const typesetAnswerIfReady = async () => {
|
264 |
if (window.mathJaxReady) {
|
265 |
MathJax.startup.document.elements = [document.getElementById('answerContent')];
|
266 |
await MathJax.typesetPromise();
|
267 |
answerContent.scrollTop = answerContent.scrollHeight;
|
268 |
+
} else { setTimeout(typesetAnswerIfReady, 200); }
|
|
|
|
|
269 |
};
|
270 |
const updateDisplay = async () => {
|
271 |
+
thoughtsContent.innerHTML = marked.parse(thoughtsBuffer);
|
272 |
+
answerContent.innerHTML = marked.parse(answerBuffer);
|
|
|
|
|
|
|
273 |
await typesetAnswerIfReady();
|
274 |
updateTimeout = null;
|
275 |
};
|
|
|
394 |
openSaved.addEventListener('click', () => { loadSavedList(); savedModal.classList.add('active'); });
|
395 |
closeSaved.addEventListener('click', () => { savedModal.classList.remove('active'); });
|
396 |
|
397 |
+
// Bouton présent uniquement dans le modal pour lancer un nouvel exercice
|
398 |
newExercise.addEventListener('click', () => {
|
399 |
form.reset();
|
400 |
form.classList.remove('hidden');
|
|
|
409 |
});
|
410 |
</script>
|
411 |
</body>
|
412 |
+
</html>
|
413 |
+
|