Ajout paramètre message bas de page personnalisable

This commit is contained in:
Yannick Le Duc
2025-08-27 12:21:09 +02:00
parent 28df167fee
commit aa859a1e44
15 changed files with 580 additions and 207 deletions

View File

@@ -18,39 +18,95 @@ export function parseMarkdown(content: string): string {
// Nettoyer le contenu avant parsing
const cleanContent = content.trim();
// Parser le markdown avec des regex simples et sécurisées
let htmlContent = cleanContent
// Échapper les caractères HTML
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
// Parser le markdown de base
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/__(.*?)__/g, '<u>$1</u>')
.replace(/~~(.*?)~~/g, '<del>$1</del>')
// Parser les liens avec validation
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
if (isValidUrl(url)) {
return `<a href="${url}" target="_blank" rel="noopener noreferrer">${text}</a>`;
}
return text; // Retourner juste le texte si l'URL n'est pas valide
})
// Parser les titres
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
// Parser les listes
.replace(/^- (.*$)/gim, '<li>$1</li>')
.replace(/^\d+\. (.*$)/gim, '<li>$1</li>')
// Parser les paragraphes
.replace(/\n\n/g, '</p><p>')
.replace(/\n/g, '<br>');
// Diviser le contenu en lignes pour traiter les listes correctement
const lines = cleanContent.split('\n');
const processedLines: string[] = [];
let inUnorderedList = false;
let inOrderedList = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// Échapper les caractères HTML
let processedLine = line
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
// Parser le markdown de base
processedLine = processedLine
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/__(.*?)__/g, '<u>$1</u>')
.replace(/~~(.*?)~~/g, '<del>$1</del>')
// Parser les liens avec validation
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (match, text, url) => {
if (isValidUrl(url)) {
return `<a href="${url}" target="_blank" rel="noopener noreferrer">${text}</a>`;
}
return text; // Retourner juste le texte si l'URL n'est pas valide
});
// Traiter les titres
if (processedLine.match(/^### /)) {
processedLine = processedLine.replace(/^### (.*$)/, '<h3>$1</h3>');
} else if (processedLine.match(/^## /)) {
processedLine = processedLine.replace(/^## (.*$)/, '<h2>$1</h2>');
} else if (processedLine.match(/^# /)) {
processedLine = processedLine.replace(/^# (.*$)/, '<h1>$1</h1>');
}
// Traiter les listes à puce
if (processedLine.match(/^- /)) {
if (!inUnorderedList) {
processedLine = '<ul>' + processedLine.replace(/^- (.*$)/, '<li>$1</li>');
inUnorderedList = true;
} else {
processedLine = processedLine.replace(/^- (.*$)/, '<li>$1</li>');
}
} else if (processedLine.match(/^\d+\. /)) {
if (!inOrderedList) {
processedLine = '<ol>' + processedLine.replace(/^\d+\. (.*$)/, '<li>$1</li>');
inOrderedList = true;
} else {
processedLine = processedLine.replace(/^\d+\. (.*$)/, '<li>$1</li>');
}
} else {
// Ligne normale - fermer les listes si nécessaire
if (inUnorderedList) {
processedLine = '</ul>' + processedLine;
inUnorderedList = false;
}
if (inOrderedList) {
processedLine = '</ol>' + processedLine;
inOrderedList = false;
}
// Traiter les paragraphes
if (processedLine.trim() === '') {
processedLine = '</p><p>';
} else {
processedLine = processedLine + '<br>';
}
}
processedLines.push(processedLine);
}
// Fermer les listes ouvertes à la fin
if (inUnorderedList) {
processedLines.push('</ul>');
}
if (inOrderedList) {
processedLines.push('</ol>');
}
let htmlContent = processedLines.join('\n');
// Ajouter les balises de paragraphe si nécessaire
if (!htmlContent.startsWith('<h') && !htmlContent.startsWith('<li')) {
if (!htmlContent.startsWith('<h') && !htmlContent.startsWith('<ul') && !htmlContent.startsWith('<ol')) {
htmlContent = `<p>${htmlContent}</p>`;
}
@@ -101,25 +157,93 @@ export function parseMarkdown(content: string): string {
export function previewMarkdown(content: string): string {
if (!content) return '';
// Remplacer les caractères spéciaux pour la prévisualisation
return content
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/__(.*?)__/g, '<u>$1</u>')
.replace(/~~(.*?)~~/g, '<del>$1</del>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>')
.replace(/^### (.*$)/gim, '<h3>$1</h3>')
.replace(/^## (.*$)/gim, '<h2>$1</h2>')
.replace(/^# (.*$)/gim, '<h1>$1</h1>')
.replace(/^- (.*$)/gim, '<li>$1</li>')
.replace(/^\d+\. (.*$)/gim, '<li>$1</li>')
.replace(/\n\n/g, '</p><p>')
.replace(/\n/g, '<br>');
// Diviser le contenu en lignes pour traiter les listes correctement
const lines = content.split('\n');
const processedLines: string[] = [];
let inUnorderedList = false;
let inOrderedList = false;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
// Échapper les caractères HTML
let processedLine = line
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
// Traiter le markdown de base
processedLine = processedLine
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.*?)\*/g, '<em>$1</em>')
.replace(/__(.*?)__/g, '<u>$1</u>')
.replace(/~~(.*?)~~/g, '<del>$1</del>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>');
// Traiter les titres
if (processedLine.match(/^### /)) {
processedLine = processedLine.replace(/^### (.*$)/, '<h3>$1</h3>');
} else if (processedLine.match(/^## /)) {
processedLine = processedLine.replace(/^## (.*$)/, '<h2>$1</h2>');
} else if (processedLine.match(/^# /)) {
processedLine = processedLine.replace(/^# (.*$)/, '<h1>$1</h1>');
}
// Traiter les listes à puce
if (processedLine.match(/^- /)) {
if (!inUnorderedList) {
processedLine = '<ul>' + processedLine.replace(/^- (.*$)/, '<li>$1</li>');
inUnorderedList = true;
} else {
processedLine = processedLine.replace(/^- (.*$)/, '<li>$1</li>');
}
} else if (processedLine.match(/^\d+\. /)) {
if (!inOrderedList) {
processedLine = '<ol>' + processedLine.replace(/^\d+\. (.*$)/, '<li>$1</li>');
inOrderedList = true;
} else {
processedLine = processedLine.replace(/^\d+\. (.*$)/, '<li>$1</li>');
}
} else {
// Ligne normale - fermer les listes si nécessaire
if (inUnorderedList) {
processedLine = '</ul>' + processedLine;
inUnorderedList = false;
}
if (inOrderedList) {
processedLine = '</ol>' + processedLine;
inOrderedList = false;
}
// Traiter les paragraphes
if (processedLine.trim() === '') {
processedLine = '</p><p>';
} else {
processedLine = processedLine + '<br>';
}
}
processedLines.push(processedLine);
}
// Fermer les listes ouvertes à la fin
if (inUnorderedList) {
processedLines.push('</ul>');
}
if (inOrderedList) {
processedLines.push('</ol>');
}
let result = processedLines.join('\n');
// Ajouter les balises de paragraphe si nécessaire
if (!result.startsWith('<h') && !result.startsWith('<ul') && !result.startsWith('<ol')) {
result = '<p>' + result + '</p>';
}
return result;
}
// Fonction pour valider le contenu markdown avant sauvegarde