mirror of
https://forge.chapril.org/tykayn/book_generator
synced 2025-06-20 01:34:43 +02:00
159 lines
No EOL
4.9 KiB
JavaScript
159 lines
No EOL
4.9 KiB
JavaScript
let enable_auto_update = false;
|
|
let previewTimeout = null;
|
|
let isScrolling = false;
|
|
|
|
// Gestion du thème
|
|
const themeSwitch = document.getElementById('theme-switch');
|
|
const htmlElement = document.documentElement;
|
|
|
|
// Charger le thème sauvegardé
|
|
const savedTheme = localStorage.getItem('theme') || 'light';
|
|
htmlElement.setAttribute('data-theme', savedTheme);
|
|
themeSwitch.checked = savedTheme === 'dark';
|
|
|
|
// Écouteur d'événements pour le switch de thème
|
|
themeSwitch.addEventListener('change', (e) => {
|
|
const theme = e.target.checked ? 'dark' : 'light';
|
|
htmlElement.setAttribute('data-theme', theme);
|
|
localStorage.setItem('theme', theme);
|
|
});
|
|
|
|
// Fonction pour convertir le texte org en HTML
|
|
function orgToHtml(text) {
|
|
// Conversion des titres
|
|
text = text.replace(/^\*+ (.*)$/gm, (match, content) => {
|
|
const level = match.match(/^\*+/)[0].length;
|
|
return `<h${level} class="org-heading">${content}</h${level}>`;
|
|
});
|
|
|
|
// Conversion des listes
|
|
text = text.replace(/^- (.*)$/gm, '<li>$1</li>');
|
|
text = text.replace(/(<li>.*<\/li>\n?)+/g, '<ul>$&</ul>');
|
|
|
|
// Conversion des citations
|
|
text = text.replace(/^#\+BEGIN_QUOTE\n(.*?)\n#\+END_QUOTE$/gs, '<blockquote>$1</blockquote>');
|
|
|
|
// Conversion du code
|
|
text = text.replace(/^#\+BEGIN_SRC.*\n(.*?)\n#\+END_SRC$/gs, '<pre><code>$1</code></pre>');
|
|
text = text.replace(/`([^`]+)`/g, '<code>$1</code>');
|
|
|
|
// Conversion des paragraphes
|
|
text = text.split('\n\n').map(para => {
|
|
if (!para.trim()) return '';
|
|
if (!para.match(/^<[hul]|^<blockquote|^<pre/)) {
|
|
return `<p>${para}</p>`;
|
|
}
|
|
return para;
|
|
}).join('\n');
|
|
|
|
return text;
|
|
}
|
|
|
|
// Fonction pour mettre à jour la prévisualisation
|
|
function updatePreview() {
|
|
const content = document.getElementById('editor-content').value;
|
|
const previewContent = document.getElementById('preview-content');
|
|
previewContent.innerHTML = orgToHtml(content);
|
|
}
|
|
|
|
// Synchronisation du défilement
|
|
function syncScroll(source, target) {
|
|
if (isScrolling) return;
|
|
isScrolling = true;
|
|
|
|
const sourceScrollPercent = source.scrollTop / (source.scrollHeight - source.clientHeight);
|
|
const targetScrollTop = sourceScrollPercent * (target.scrollHeight - target.clientHeight);
|
|
target.scrollTop = targetScrollTop;
|
|
|
|
setTimeout(() => {
|
|
isScrolling = false;
|
|
}, 100);
|
|
}
|
|
|
|
// Écouteurs d'événements pour la synchronisation du défilement
|
|
const editor = document.getElementById('editor-content');
|
|
const preview = document.getElementById('preview-content');
|
|
|
|
editor.addEventListener('scroll', () => {
|
|
syncScroll(editor, preview);
|
|
});
|
|
|
|
preview.addEventListener('scroll', () => {
|
|
syncScroll(preview, editor);
|
|
});
|
|
|
|
// Écouteur d'événements pour la mise à jour automatique de la prévisualisation
|
|
editor.addEventListener('input', () => {
|
|
if (document.getElementById('auto-preview').checked) {
|
|
clearTimeout(previewTimeout);
|
|
previewTimeout = setTimeout(updatePreview, 500);
|
|
}
|
|
});
|
|
|
|
// Écouteur d'événements pour le switch de mise à jour automatique
|
|
document.getElementById('auto-preview').addEventListener('change', (e) => {
|
|
if (e.target.checked) {
|
|
updatePreview();
|
|
}
|
|
});
|
|
|
|
// Sauvegarde automatique si activée
|
|
if (enable_auto_update) {
|
|
setInterval(async () => {
|
|
const content = document.getElementById('editor-content').value;
|
|
try {
|
|
const response = await fetch('/update', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
body: `content=${encodeURIComponent(content)}`
|
|
});
|
|
const data = await response.json();
|
|
if (response.ok) {
|
|
document.getElementById('words-today').textContent = data.words_today;
|
|
console.log('Sauvegarde automatique effectuée');
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors de la sauvegarde automatique');
|
|
}
|
|
}, 20000); // 20 secondes
|
|
}
|
|
|
|
// Mise à jour du contenu
|
|
document.getElementById('update-btn').addEventListener('click', async () => {
|
|
const content = document.getElementById('editor-content').value;
|
|
try {
|
|
const response = await fetch('/update', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
},
|
|
body: `content=${encodeURIComponent(content)}`
|
|
});
|
|
const data = await response.json();
|
|
if (response.ok) {
|
|
document.getElementById('words-today').textContent = data.words_today;
|
|
alert('Contenu mis à jour avec succès !');
|
|
}
|
|
} catch (error) {
|
|
alert('Erreur lors de la mise à jour');
|
|
}
|
|
});
|
|
|
|
// Mise à jour automatique du compteur de mots
|
|
async function updateWordCount() {
|
|
try {
|
|
const response = await fetch('/words_today');
|
|
const data = await response.json();
|
|
document.getElementById('words-today').textContent = data.words;
|
|
} catch (error) {
|
|
console.error('Erreur lors de la mise à jour du compteur de mots');
|
|
}
|
|
}
|
|
|
|
// Mise à jour toutes les 30 secondes
|
|
setInterval(updateWordCount, 30000);
|
|
|
|
// Initialisation de la prévisualisation
|
|
updatePreview();
|