Ajout paramètre message bas de page personnalisable
This commit is contained in:
@@ -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, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
// 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, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
|
||||
// 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, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.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, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
|
||||
// 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
|
||||
|
||||
@@ -578,6 +578,14 @@ export const settingsService = {
|
||||
return this.setValue(key, value.toString());
|
||||
},
|
||||
|
||||
async getStringValue(key: string, defaultValue: string = ''): Promise<string> {
|
||||
return this.getValue(key, defaultValue);
|
||||
},
|
||||
|
||||
async setStringValue(key: string, value: string): Promise<Setting> {
|
||||
return this.setValue(key, value);
|
||||
},
|
||||
|
||||
async delete(key: string): Promise<void> {
|
||||
const { error } = await supabase
|
||||
.from('settings')
|
||||
|
||||
@@ -4,3 +4,42 @@ import { twMerge } from "tailwind-merge"
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
||||
/**
|
||||
* Traite le message du footer en remplaçant [LINK] par le lien vers le repository
|
||||
*/
|
||||
export function processFooterMessage(message: string, repositoryUrl: string): string {
|
||||
return message.replace(/\[LINK\]/g, repositoryUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traite le message du footer et retourne le texte avec les liens Markdown remplacés
|
||||
*/
|
||||
export function parseFooterMessage(message: string, repositoryUrl: string): { text: string; links: Array<{ text: string; url: string; start: number; end: number }> } {
|
||||
const links: Array<{ text: string; url: string; start: number; end: number }> = [];
|
||||
let processedText = message;
|
||||
|
||||
// Remplacer [texte](GITURL) par le texte du lien
|
||||
const linkRegex = /\[([^\]]+)\]\(GITURL\)/g;
|
||||
let match;
|
||||
let offset = 0;
|
||||
|
||||
while ((match = linkRegex.exec(message)) !== null) {
|
||||
const linkText = match[1]; // Le texte entre crochets
|
||||
const fullMatch = match[0]; // Le match complet [texte](GITURL)
|
||||
const start = match.index + offset;
|
||||
const end = start + linkText.length;
|
||||
|
||||
links.push({
|
||||
text: linkText,
|
||||
url: repositoryUrl,
|
||||
start,
|
||||
end
|
||||
});
|
||||
|
||||
processedText = processedText.replace(fullMatch, linkText);
|
||||
offset += linkText.length - fullMatch.length;
|
||||
}
|
||||
|
||||
return { text: processedText, links };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user