diff --git a/script.js b/script.js
index 0e7f957..1e9c4c1 100644
--- a/script.js
+++ b/script.js
@@ -1,359 +1,373 @@
// Configuration globale
let config = {
- baseUrl: '',
- currentPath: ''
+ baseUrl: "",
+ currentPath: "",
};
// Initialisation de l'application
-document.addEventListener('DOMContentLoaded', function() {
- initializeApp();
- setupEventListeners();
+document.addEventListener("DOMContentLoaded", function () {
+ initializeApp();
+ setupEventListeners();
});
function initializeApp() {
- // Tentative de configuration automatique depuis l'URL courante
- autoConfigureFromURL();
-
- // Affichage du formulaire de développement
- showDevForm();
-
+ // Tentative de configuration automatique depuis l'URL courante
+ autoConfigureFromURL();
+
+ // Affichage du formulaire de développement
+ showDevForm();
}
function setupEventListeners() {
- // Formulaire de développement
- const urlForm = document.getElementById('url-form');
- if (urlForm) {
- urlForm.addEventListener('submit', handleUrlFormSubmit);
- }
-
- // Gestion de la navigation arrière/avant du navigateur
- window.addEventListener('popstate', handlePopState);
-
- // Gestionnaires pour la prévisualisation
- const closePreview = document.getElementById('close-preview');
- if (closePreview) {
- closePreview.addEventListener('click', hidePreview);
- }
-
- const downloadFile = document.getElementById('download-file');
- if (downloadFile) {
- downloadFile.addEventListener('click', downloadCurrentFile);
- }
+ // Formulaire de développement
+ const urlForm = document.getElementById("url-form");
+ if (urlForm) {
+ urlForm.addEventListener("submit", handleUrlFormSubmit);
+ }
+
+ // Gestion de la navigation arrière/avant du navigateur
+ window.addEventListener("popstate", handlePopState);
+
+ // Gestionnaires pour la prévisualisation
+ const closePreview = document.getElementById("close-preview");
+ if (closePreview) {
+ closePreview.addEventListener("click", hidePreview);
+ }
+
+ const downloadFile = document.getElementById("download-file");
+ if (downloadFile) {
+ downloadFile.addEventListener("click", downloadCurrentFile);
+ }
}
function handlePopState(event) {
- console.log('Navigation arrière/avant détectée:', event.state);
-
- if (event.state && event.state.baseUrl) {
- // Restaurer la configuration
- config.baseUrl = event.state.baseUrl;
- config.currentPath = event.state.path || '';
-
- updateConfigDisplay();
-
- // Charger le contenu sans ajouter à l'historique (pour éviter les boucles)
- loadBucketContents(config.currentPath, false);
- }
+ console.log("Navigation arrière/avant détectée:", event.state);
+
+ if (event.state && event.state.baseUrl) {
+ // Restaurer la configuration
+ config.baseUrl = event.state.baseUrl;
+ config.currentPath = event.state.path || "";
+
+ updateConfigDisplay();
+
+ // Charger le contenu sans ajouter à l'historique (pour éviter les boucles)
+ loadBucketContents(config.currentPath, false);
+ }
}
function autoConfigureFromURL() {
- const currentUrl = window.location.href;
- const url = new URL(currentUrl);
-
- // Configuration simplifiée : on prend juste le base URL sans le bucket
- config.baseUrl = `${url.protocol}//${url.host}${url.pathname.replace('/index.html', '')}`;
-
- // Vérifier s'il y a un fragment d'URL pour définir le chemin initial
- if (url.hash) {
- const hashPath = url.hash.replace('#/', '');
- config.currentPath = hashPath;
- }
-
- updateConfigDisplay();
- console.log('Configuration automatique:', config);
-
- // Charger automatiquement le contenu si on a une config valide
- if (config.baseUrl) {
- loadBucketContents(config.currentPath, false);
- }
+ const currentUrl = window.location.href;
+ const url = new URL(currentUrl);
+
+ // Configuration simplifiée : on prend juste le base URL sans le bucket
+ config.baseUrl = `${url.protocol}//${url.host}${url.pathname.replace("/index.html", "")}`;
+
+ // Vérifier s'il y a un fragment d'URL pour définir le chemin initial
+ if (url.hash) {
+ const hashPath = url.hash.replace("#/", "");
+ config.currentPath = hashPath;
+ }
+
+ updateConfigDisplay();
+ console.log("Configuration automatique:", config);
+
+ // Charger automatiquement le contenu si on a une config valide
+ if (config.baseUrl) {
+ loadBucketContents(config.currentPath, false);
+ }
}
function handleUrlFormSubmit(event) {
- event.preventDefault();
-
- const urlInput = document.getElementById('minio-url');
- if (!urlInput) return;
-
- const minioUrl = urlInput.value.trim();
-
- if (!minioUrl) {
- showError('Veuillez saisir une URL MinIO');
- return;
- }
-
- parseMinioURL(minioUrl);
+ event.preventDefault();
+
+ const urlInput = document.getElementById("minio-url");
+ if (!urlInput) return;
+
+ const minioUrl = urlInput.value.trim();
+
+ if (!minioUrl) {
+ showError("Veuillez saisir une URL MinIO");
+ return;
+ }
+
+ parseMinioURL(minioUrl);
}
function parseMinioURL(url) {
- try {
- const urlObj = new URL(url);
-
- // Configuration simplifiée : on prend l'URL complète comme base
- config.baseUrl = url.replace(/\/$/, ''); // Supprimer le slash final si présent
- config.currentPath = '';
-
- updateConfigDisplay();
-
- // Ajouter l'état initial à l'historique
- const initialState = { path: '', baseUrl: config.baseUrl };
- history.replaceState(initialState, '', window.location.href);
-
- loadBucketContents();
-
- } catch (error) {
- showError('URL invalide: ' + error.message);
- console.error('Erreur de parsing URL:', error);
- }
+ try {
+ const urlObj = new URL(url);
+
+ // Configuration simplifiée : on prend l'URL complète comme base
+ config.baseUrl = url.replace(/\/$/, ""); // Supprimer le slash final si présent
+ config.currentPath = "";
+
+ updateConfigDisplay();
+
+ // Ajouter l'état initial à l'historique
+ const initialState = { path: "", baseUrl: config.baseUrl };
+ history.replaceState(initialState, "", window.location.href);
+
+ loadBucketContents();
+ } catch (error) {
+ showError("URL invalide: " + error.message);
+ console.error("Erreur de parsing URL:", error);
+ }
}
function updateConfigDisplay() {
- const configInfo = document.getElementById('config-info');
- if (configInfo) {
- configInfo.innerHTML = `
+ const configInfo = document.getElementById("config-info");
+ if (configInfo) {
+ configInfo.innerHTML = `
Configuration actuelle:
URL de base: ${config.baseUrl}
Chemin actuel: /${config.currentPath}
`;
- }
+ }
}
function showDevForm() {
- const devForm = document.getElementById('dev-form');
- if (devForm) {
- devForm.style.display = 'block';
- }
+ const devForm = document.getElementById("dev-form");
+ if (devForm) {
+ devForm.style.display = "block";
+ }
}
-
function showError(message) {
- const errorSection = document.getElementById('error-section');
- const errorMessage = document.getElementById('error-message');
-
- if (errorMessage) {
- errorMessage.textContent = message;
- }
-
- if (errorSection) {
- errorSection.style.display = 'block';
-
- // Masquer l'erreur après 5 secondes
- setTimeout(() => {
- errorSection.style.display = 'none';
- }, 5000);
- }
+ const errorSection = document.getElementById("error-section");
+ const errorMessage = document.getElementById("error-message");
+
+ if (errorMessage) {
+ errorMessage.textContent = message;
+ }
+
+ if (errorSection) {
+ errorSection.style.display = "block";
+
+ // Masquer l'erreur après 5 secondes
+ setTimeout(() => {
+ errorSection.style.display = "none";
+ }, 5000);
+ }
}
function showLoading(show = true) {
- const loading = document.getElementById('loading');
- const table = document.getElementById('files-table');
-
- if (loading) {
- loading.style.display = show ? 'block' : 'none';
- }
-
- if (table) {
- table.style.display = show ? 'none' : 'table';
- }
+ const loading = document.getElementById("loading");
+ const table = document.getElementById("files-table");
+
+ if (loading) {
+ loading.style.display = show ? "block" : "none";
+ }
+
+ if (table) {
+ table.style.display = show ? "none" : "table";
+ }
}
function updateCurrentPathDisplay() {
- const pathDisplay = document.getElementById('current-path');
- if (pathDisplay) {
- pathDisplay.textContent = '/' + config.currentPath;
- }
+ const pathDisplay = document.getElementById("current-path");
+ if (pathDisplay) {
+ pathDisplay.textContent = "/" + config.currentPath;
+ }
}
-async function loadBucketContents(path = '', pushToHistory = true) {
- console.log('Debug loadBucketContents - path received:', JSON.stringify(path));
-
- if (!config.baseUrl) {
- showError('Configuration URL manquante');
- return;
+async function loadBucketContents(path = "", pushToHistory = true) {
+ console.log(
+ "Debug loadBucketContents - path received:",
+ JSON.stringify(path),
+ );
+
+ if (!config.baseUrl) {
+ showError("Configuration URL manquante");
+ return;
+ }
+
+ showLoading(true);
+ config.currentPath = path;
+ updateCurrentPathDisplay();
+
+ // Ajouter à l'historique du navigateur si demandé
+ if (pushToHistory) {
+ const state = { path: path, baseUrl: config.baseUrl };
+ const url = path ? `#/${path}` : "#/";
+ history.pushState(state, "", url);
+ }
+
+ try {
+ // Construction de l'URL API avec delimiter
+ let apiUrl = `${config.baseUrl}?list-type=2&delimiter=/`;
+
+ // Construire le prefix pour l'API MinIO
+ if (path) {
+ // Pour un sous-dossier
+ const cleanPath = path.startsWith("/") ? path.substring(1) : path;
+ const fullPrefix = cleanPath + "/";
+ apiUrl += `&prefix=${encodeURIComponent(fullPrefix)}`;
}
-
- showLoading(true);
- config.currentPath = path;
- updateCurrentPathDisplay();
-
- // Ajouter à l'historique du navigateur si demandé
- if (pushToHistory) {
- const state = { path: path, baseUrl: config.baseUrl };
- const url = path ? `#/${path}` : '#/';
- history.pushState(state, '', url);
- }
-
- try {
- // Construction de l'URL API avec delimiter
- let apiUrl = `${config.baseUrl}?list-type=2&delimiter=/`;
-
- // Construire le prefix pour l'API MinIO
- if (path) {
- // Pour un sous-dossier
- const cleanPath = path.startsWith('/') ? path.substring(1) : path;
- const fullPrefix = cleanPath + '/';
- apiUrl += `&prefix=${encodeURIComponent(fullPrefix)}`;
- }
-
- console.log('Appel API MinIO:', apiUrl);
-
- const response = await fetch(apiUrl);
-
- if (!response.ok) {
- throw new Error(`Erreur HTTP: ${response.status}`);
- }
-
- const xmlText = await response.text();
- console.log('Réponse XML reçue:', xmlText);
-
- const contents = parseMinioXML(xmlText);
- displayContents(contents);
-
- } catch (error) {
- console.error('Erreur lors du chargement:', error);
- showError('Erreur de chargement: ' + error.message);
- } finally {
- showLoading(false);
+
+ console.log("Appel API MinIO:", apiUrl);
+
+ const response = await fetch(apiUrl);
+
+ if (!response.ok) {
+ throw new Error(`Erreur HTTP: ${response.status}`);
}
+
+ const xmlText = await response.text();
+ console.log("Réponse XML reçue:", xmlText);
+
+ const contents = parseMinioXML(xmlText);
+ displayContents(contents);
+ } catch (error) {
+ console.error("Erreur lors du chargement:", error);
+ showError("Erreur de chargement: " + error.message);
+ } finally {
+ showLoading(false);
+ }
}
function parseMinioXML(xmlText) {
- const parser = new DOMParser();
- const xmlDoc = parser.parseFromString(xmlText, 'text/xml');
-
- const contents = {
- folders: [],
- files: []
- };
-
- // Déterminer le préfixe attendu basé sur la navigation actuelle
- let expectedPrefix = '';
- if (config.currentPath) {
- expectedPrefix = config.currentPath + '/';
- }
-
- // Parse CommonPrefixes (dossiers)
- const prefixes = xmlDoc.getElementsByTagName('CommonPrefixes');
- for (let prefix of prefixes) {
- const prefixElement = prefix.getElementsByTagName('Prefix')[0];
- if (prefixElement) {
- const fullPrefix = prefixElement.textContent;
-
- // Extraire le nom du dossier (dernière partie avant le /)
- const folderName = fullPrefix.replace(/\/$/, '').split('/').pop();
-
- if (folderName) {
- // Construire le chemin pour la navigation
- let folderPath;
- if (config.currentPath) {
- folderPath = config.currentPath + '/' + folderName;
- } else {
- folderPath = folderName;
- }
-
- console.log('Debug parsing - fullPrefix:', fullPrefix, 'folderName:', folderName, 'currentPath:', config.currentPath, 'folderPath:', folderPath);
-
- contents.folders.push({
- name: folderName,
- path: folderPath
- });
- }
+ const parser = new DOMParser();
+ const xmlDoc = parser.parseFromString(xmlText, "text/xml");
+
+ const contents = {
+ folders: [],
+ files: [],
+ };
+
+ // Déterminer le préfixe attendu basé sur la navigation actuelle
+ let expectedPrefix = "";
+ if (config.currentPath) {
+ expectedPrefix = config.currentPath + "/";
+ }
+
+ // Parse CommonPrefixes (dossiers)
+ const prefixes = xmlDoc.getElementsByTagName("CommonPrefixes");
+ for (let prefix of prefixes) {
+ const prefixElement = prefix.getElementsByTagName("Prefix")[0];
+ if (prefixElement) {
+ const fullPrefix = prefixElement.textContent;
+
+ // Extraire le nom du dossier (dernière partie avant le /)
+ const folderName = fullPrefix.replace(/\/$/, "").split("/").pop();
+
+ if (folderName) {
+ // Construire le chemin pour la navigation
+ let folderPath;
+ if (config.currentPath) {
+ folderPath = config.currentPath + "/" + folderName;
+ } else {
+ folderPath = folderName;
}
+
+ console.log(
+ "Debug parsing - fullPrefix:",
+ fullPrefix,
+ "folderName:",
+ folderName,
+ "currentPath:",
+ config.currentPath,
+ "folderPath:",
+ folderPath,
+ );
+
+ contents.folders.push({
+ name: folderName,
+ path: folderPath,
+ });
+ }
}
-
- // Parse Contents (fichiers)
- const objects = xmlDoc.getElementsByTagName('Contents');
- for (let obj of objects) {
- const keyElement = obj.getElementsByTagName('Key')[0];
- const sizeElement = obj.getElementsByTagName('Size')[0];
- const modifiedElement = obj.getElementsByTagName('LastModified')[0];
-
- if (keyElement) {
- const fullKey = keyElement.textContent;
- const fileName = fullKey.split('/').pop();
-
- // Vérifier que le fichier correspond au niveau de navigation actuel
- let shouldInclude = false;
-
- if (config.currentPath) {
- // Dans un sous-dossier : vérifier que la clé commence par le bon préfixe
- const currentPrefix = config.currentPath + '/';
- if (fullKey.startsWith(currentPrefix)) {
- // S'assurer qu'on n'affiche que les fichiers directs (pas dans des sous-sous-dossiers)
- const relativePath = fullKey.replace(currentPrefix, '');
- if (!relativePath.includes('/')) {
- shouldInclude = true;
- }
- }
- } else {
- // À la racine : afficher tous les fichiers qui ne sont pas dans des dossiers
- if (!fullKey.includes('/')) {
- shouldInclude = true;
- }
- }
-
- // Exclure les fichiers de l'application
- if (shouldInclude && fileName && !['index.html', 'style.css', 'script.js'].includes(fileName)) {
- contents.files.push({
- name: fileName,
- size: sizeElement ? parseInt(sizeElement.textContent) : 0,
- modified: modifiedElement ? new Date(modifiedElement.textContent) : new Date(),
- fullKey: fullKey
- });
- }
+ }
+
+ // Parse Contents (fichiers)
+ const objects = xmlDoc.getElementsByTagName("Contents");
+ for (let obj of objects) {
+ const keyElement = obj.getElementsByTagName("Key")[0];
+ const sizeElement = obj.getElementsByTagName("Size")[0];
+ const modifiedElement = obj.getElementsByTagName("LastModified")[0];
+
+ if (keyElement) {
+ const fullKey = keyElement.textContent;
+ const fileName = fullKey.split("/").pop();
+
+ // Vérifier que le fichier correspond au niveau de navigation actuel
+ let shouldInclude = false;
+
+ if (config.currentPath) {
+ // Dans un sous-dossier : vérifier que la clé commence par le bon préfixe
+ const currentPrefix = config.currentPath + "/";
+ if (fullKey.startsWith(currentPrefix)) {
+ // S'assurer qu'on n'affiche que les fichiers directs (pas dans des sous-sous-dossiers)
+ const relativePath = fullKey.replace(currentPrefix, "");
+ if (!relativePath.includes("/")) {
+ shouldInclude = true;
+ }
}
+ } else {
+ // À la racine : afficher tous les fichiers qui ne sont pas dans des dossiers
+ if (!fullKey.includes("/")) {
+ shouldInclude = true;
+ }
+ }
+
+ // Exclure les fichiers de l'application
+ if (
+ shouldInclude &&
+ fileName &&
+ !["index.html", "style.css", "script.js"].includes(fileName)
+ ) {
+ contents.files.push({
+ name: fileName,
+ size: sizeElement ? parseInt(sizeElement.textContent) : 0,
+ modified: modifiedElement
+ ? new Date(modifiedElement.textContent)
+ : new Date(),
+ fullKey: fullKey,
+ });
+ }
}
-
- return contents;
+ }
+
+ return contents;
}
function displayContents(contents) {
- const tbody = document.getElementById('files-tbody');
- if (!tbody) return;
-
- tbody.innerHTML = '';
-
- // Bouton parent directory si on n'est pas à la racine
- if (config.currentPath) {
- const parentPath = config.currentPath.split('/').slice(0, -1).join('/');
- const parentRow = createParentRow(parentPath);
- tbody.appendChild(parentRow);
- }
-
- // Afficher les dossiers
- contents.folders.forEach(folder => {
- const row = createFolderRow(folder);
- tbody.appendChild(row);
- });
-
- // Afficher les fichiers
- contents.files.forEach(file => {
- const row = createFileRow(file);
- tbody.appendChild(row);
- });
-
- // Afficher le tableau
- const filesTable = document.getElementById('files-table');
- if (filesTable) {
- filesTable.style.display = 'table';
- }
-
- // Chercher et ouvrir automatiquement index.rst s'il existe
- autoOpenIndexRst(contents.files);
+ const tbody = document.getElementById("files-tbody");
+ if (!tbody) return;
+
+ tbody.innerHTML = "";
+
+ // Bouton parent directory si on n'est pas à la racine
+ if (config.currentPath) {
+ const parentPath = config.currentPath.split("/").slice(0, -1).join("/");
+ const parentRow = createParentRow(parentPath);
+ tbody.appendChild(parentRow);
+ }
+
+ // Afficher les dossiers
+ contents.folders.forEach((folder) => {
+ const row = createFolderRow(folder);
+ tbody.appendChild(row);
+ });
+
+ // Afficher les fichiers
+ contents.files.forEach((file) => {
+ const row = createFileRow(file);
+ tbody.appendChild(row);
+ });
+
+ // Afficher le tableau
+ const filesTable = document.getElementById("files-table");
+ if (filesTable) {
+ filesTable.style.display = "table";
+ }
+
+ // Chercher et ouvrir automatiquement index.rst s'il existe
+ autoOpenIndexRst(contents.files);
}
function createParentRow(parentPath) {
- const row = document.createElement('tr');
- row.innerHTML = `
+ const row = document.createElement("tr");
+ row.innerHTML = `
Prévisualisation non disponible pour ce type de fichier (.${extension})
Utilisez le bouton "Télécharger" ci-dessous pour obtenir le fichier.
@@ -720,323 +757,354 @@ function showUnsupportedPreview(fileName, container) { } function hidePreview() { - const previewSection = document.getElementById('preview-section'); - if (previewSection) { - previewSection.style.display = 'none'; - } - - currentPreviewFile = { url: '', name: '' }; + const previewSection = document.getElementById("preview-section"); + if (previewSection) { + previewSection.style.display = "none"; + } + + currentPreviewFile = { url: "", name: "" }; } function downloadCurrentFile() { - if (currentPreviewFile.url) { - const link = document.createElement('a'); - link.href = currentPreviewFile.url; - link.download = currentPreviewFile.name; - link.target = '_blank'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } + if (currentPreviewFile.url) { + const link = document.createElement("a"); + link.href = currentPreviewFile.url; + link.download = currentPreviewFile.name; + link.target = "_blank"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + } } // Fonction pour ouvrir automatiquement index.rst s'il existe function autoOpenIndexRst(files) { - // Chercher un fichier index.rst dans la liste - const indexRstFile = files.find(file => - file.name.toLowerCase() === 'index.rst' - ); - - if (indexRstFile) { - // Construire l'URL complète du fichier - const fileUrl = `${config.baseUrl}/${indexRstFile.fullKey}`; - - // Ouvrir automatiquement la prévisualisation - console.log('Auto-ouverture de index.rst trouvé:', indexRstFile.name); - showPreview(fileUrl, indexRstFile.name); - } else { - // Pas d'index.rst trouvé, fermer le preview s'il est ouvert - console.log('Aucun index.rst trouvé, fermeture du preview'); - hidePreview(); - } + // Chercher un fichier index.rst dans la liste + const indexRstFile = files.find( + (file) => file.name.toLowerCase() === "index.rst", + ); + + if (indexRstFile) { + // Construire l'URL complète du fichier + const fileUrl = `${config.baseUrl}/${indexRstFile.fullKey}`; + + // Ouvrir automatiquement la prévisualisation + console.log("Auto-ouverture de index.rst trouvé:", indexRstFile.name); + showPreview(fileUrl, indexRstFile.name); + } else { + // Pas d'index.rst trouvé, fermer le preview s'il est ouvert + console.log("Aucun index.rst trouvé, fermeture du preview"); + hidePreview(); + } } // Fonction simple de parsing Markdown vers HTML function parseMarkdown(text) { - let html = text; - - // Headers - html = html.replace(/^### (.*$)/gim, '$1');
-
- // Code blocks
- html = html.replace(/```([\s\S]*?)```/g, '$1');
-
- // Links
- html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1');
-
- // Images
- html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, ''); - html = '
' + html + '
'; - - // Clean up empty paragraphs - html = html.replace(/<\/p>/g, ''); - html = html.replace(/
( ( ()/g, '$1');
- html = html.replace(/(<\/ul>)<\/p>/g, '$1');
- html = html.replace(/
)/g, '$1');
- html = html.replace(/(<\/pre>)<\/p>/g, '$1');
-
- return html;
+ let html = text;
+
+ // Headers
+ html = html.replace(/^### (.*$)/gim, "
$1
");
+ html = html.replace(/^## (.*$)/gim, "$1
");
+ html = html.replace(/^# (.*$)/gim, "$1
");
+
+ // Bold
+ html = html.replace(/\*\*(.*?)\*\*/g, "$1");
+ html = html.replace(/__(.*?)__/g, "$1");
+
+ // Italic
+ html = html.replace(/\*(.*?)\*/g, "$1");
+ html = html.replace(/_(.*?)_/g, "$1");
+
+ // Code inline
+ html = html.replace(/`(.*?)`/g, "$1");
+
+ // Code blocks
+ html = html.replace(/```([\s\S]*?)```/g, "
");
+
+ // Links
+ html = html.replace(
+ /\[([^\]]+)\]\(([^)]+)\)/g,
+ '$1',
+ );
+
+ // Images
+ html = html.replace(
+ /!\[([^\]]*)\]\(([^)]+)\)/g,
+ '$1',
+ );
+
+ // Lists
+ html = html.replace(/^\* (.*$)/gim, "
+ html = html.replace(/(
" + match + "
";
+ });
+
+ // Line breaks
+ html = html.replace(/\n\n/g, "
"); + html = "
" + html + "
"; + + // Clean up empty paragraphs + html = html.replace(/<\/p>/g, ""); + html = html.replace(/
( ( ()/g, "$1");
+ html = html.replace(/(<\/ul>)<\/p>/g, "$1");
+ html = html.replace(/
)/g, "$1");
+ html = html.replace(/(<\/pre>)<\/p>/g, "$1");
+
+ return html;
}
// Fonction simple de parsing reStructuredText vers HTML
function parseRst(text) {
- let html = text;
-
- // Créer un système de placeholders pour éviter les liens imbriqués
- const linkPlaceholders = new Map();
- let placeholderIndex = 0;
-
- // Fonction pour créer un placeholder unique
- const createLinkPlaceholder = (linkText, linkUrl) => {
- const placeholder = `__LINK_PLACEHOLDER_${placeholderIndex++}__`;
- linkPlaceholders.set(placeholder, `${linkText}`);
- return placeholder;
- };
-
- // Headers (RST style with underlines) - ordre important pour éviter les conflits
- html = html.replace(/^(.*)\n#{3,}$/gim, '$1
');
- html = html.replace(/^(.*)\n={3,}$/gim, '$1
');
- html = html.replace(/^(.*)\n-{3,}$/gim, '$1
');
- html = html.replace(/^(.*)\n~{3,}$/gim, '$1
');
- html = html.replace(/^(.*)\n\^{3,}$/gim, '$1
');
-
- // Metadata fields
- html = html.replace(/^:([^:]+):\s*(.*)$/gim, (match, key, value) => {
- // Remplacer les liens par des placeholders dans les métadonnées
- const processedValue = value.replace(/`([^<]+) <([^>]+)>`_/g, (match, text, url) => {
- return createLinkPlaceholder(text, url);
- });
- return ``;
- });
-
- // Process directives with their options and content - regex corrigée pour s'arrêter aux lignes non indentées
- html = html.replace(/\.\. ([^:]+)::([\s\S]*?)(?=\n\S|\.\.|$)/g, (match, directive, block) => {
- // Gestion spéciale pour big_button
- const isBigButton = directive === 'big_button';
- const className = isBigButton ? 'rst-big-button' : `rst-directive rst-directive-${directive}`;
-
- let result = `$1');
-
- // Code blocks (:: at end of line followed by indented block)
- html = html.replace(/::\s*\n\n((?: .*\n?)+)/g, '
');
-
- // Links restants dans le texte principal
- html = html.replace(/`([^<]+) <([^>]+)>`_/g, (match, text, url) => {
+ let html = text;
+
+ // Créer un système de placeholders pour éviter les liens imbriqués
+ const linkPlaceholders = new Map();
+ let placeholderIndex = 0;
+
+ // Fonction pour créer un placeholder unique
+ const createLinkPlaceholder = (linkText, linkUrl) => {
+ const placeholder = `__LINK_PLACEHOLDER_${placeholderIndex++}__`;
+ linkPlaceholders.set(
+ placeholder,
+ `${linkText}`,
+ );
+ return placeholder;
+ };
+
+ // Headers (RST style with underlines) - ordre important pour éviter les conflits
+ html = html.replace(/^(.*)\n#{3,}$/gim, "$1$1
");
+ html = html.replace(/^(.*)\n={3,}$/gim, "$1
");
+ html = html.replace(/^(.*)\n-{3,}$/gim, "$1
");
+ html = html.replace(/^(.*)\n~{3,}$/gim, "$1
");
+ html = html.replace(/^(.*)\n\^{3,}$/gim, "$1
");
+
+ // Metadata fields
+ html = html.replace(/^:([^:]+):\s*(.*)$/gim, (match, key, value) => {
+ // Remplacer les liens par des placeholders dans les métadonnées
+ const processedValue = value.replace(
+ /`([^<]+) <([^>]+)>`_/g,
+ (match, text, url) => {
return createLinkPlaceholder(text, url);
- });
-
- // Lists
- html = html.replace(/^\* (.*$)/gim, '
- html = html.replace(/(
' + match + '
';
- });
-
- // Line breaks
- html = html.replace(/\n\n/g, '
'); - html = '
' + html + '
'; - - // Clean up empty paragraphs and fix structure - html = html.replace(/<\/p>/g, ''); - html = html.replace(/
( ( ( ( ");
+ html = " " + html + " <\/p>/g, "");
+ html = html.replace(/ ( ( ( ()/g, '$1');
- html = html.replace(/(<\/ul>)<\/p>/g, '$1');
- html = html.replace(/
)/g, '$1');
- html = html.replace(/(<\/pre>)<\/p>/g, '$1');
-
- // Restaurer tous les liens à partir des placeholders
- for (const [placeholder, linkHtml] of linkPlaceholders) {
- html = html.replace(new RegExp(placeholder, 'g'), linkHtml);
- }
-
- return html;
+ },
+ );
+ return ``;
+ });
+
+ // Process directives with their options and content - regex corrigée pour s'arrêter aux lignes non indentées
+ html = html.replace(
+ /\.\. ([^:]+)::([\s\S]*?)(?=\n\S|\.\.|$)/g,
+ (match, directive, block) => {
+ // Gestion spéciale pour big_button
+ const isBigButton = directive === "big_button";
+ const className = isBigButton
+ ? "rst-big-button"
+ : `rst-directive rst-directive-${directive}`;
+
+ let result = `$1");
+
+ // Code blocks (:: at end of line followed by indented block)
+ html = html.replace(
+ /::\s*\n\n((?: .*\n?)+)/g,
+ "
",
+ );
+
+ // Links restants dans le texte principal
+ html = html.replace(/`([^<]+) <([^>]+)>`_/g, (match, text, url) => {
+ return createLinkPlaceholder(text, url);
+ });
+
+ // Lists
+ html = html.replace(/^\* (.*$)/gim, "$1
+ html = html.replace(/(
" + match + "
";
+ });
+
+ // Line breaks
+ html = html.replace(/\n\n/g, ")/g, "$1");
+ html = html.replace(/(<\/ul>)<\/p>/g, "$1");
+ html = html.replace(/
)/g, "$1");
+ html = html.replace(/(<\/pre>)<\/p>/g, "$1");
+
+ // Restaurer tous les liens à partir des placeholders
+ for (const [placeholder, linkHtml] of linkPlaceholders) {
+ html = html.replace(new RegExp(placeholder, "g"), linkHtml);
+ }
+
+ return html;
}
function showMarkdownPreview(fileUrl, container) {
- fetch(fileUrl)
- .then(response => {
- if (!response.ok) {
- throw new Error(`Erreur HTTP: ${response.status}`);
- }
- return response.text();
- })
- .then(text => {
- const htmlContent = parseMarkdown(text);
- const div = document.createElement('div');
- div.className = 'markdown-content';
- div.innerHTML = htmlContent;
- container.innerHTML = '';
- container.appendChild(div);
- })
- .catch(error => {
- console.error('Erreur chargement markdown:', error);
- container.innerHTML = '