- composables/useMarkdown.ts : renderer MD léger (bold/italic/listes/titres) - ChatbotSheet.vue + trouver-du-taf.vue : v-html renderMd() sur messages bot - assets/css/main.css : styles .md-content globaux pour tous les chatbots - taff-header centré + phrase cible 'architectes indépendants, 70% de la profession' Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
36 lines
1.4 KiB
TypeScript
36 lines
1.4 KiB
TypeScript
/**
|
|
* Convertit du Markdown Mistral en HTML sécurisé.
|
|
* Gère : **bold**, *italic*, ## titres, listes - et •, retours à la ligne.
|
|
* Pas de dépendance externe.
|
|
*/
|
|
export function useMarkdown() {
|
|
function render(text: string): string {
|
|
if (!text) return ''
|
|
let html = text
|
|
// Échappement XSS de base
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
// Titres ## et ###
|
|
.replace(/^### (.+)$/gm, '<strong class="md-h3">$1</strong>')
|
|
.replace(/^## (.+)$/gm, '<strong class="md-h2">$1</strong>')
|
|
.replace(/^# (.+)$/gm, '<strong class="md-h1">$1</strong>')
|
|
// Bold et italic
|
|
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
|
|
.replace(/\*(.+?)\*/g, '<em>$1</em>')
|
|
// Listes (- item ou • item en début de ligne)
|
|
.replace(/^[-•]\s+(.+)$/gm, '<li>$1</li>')
|
|
// Liens [texte](url)
|
|
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener" class="md-link">$1</a>')
|
|
// Grouper les <li> consécutifs dans un <ul>
|
|
html = html.replace(/(<li>.*<\/li>\n?)+/g, match => `<ul class="md-list">${match}</ul>`)
|
|
// Paragraphes : double saut de ligne → séparateur
|
|
html = html.replace(/\n{2,}/g, '</p><p>')
|
|
// Saut de ligne simple → <br>
|
|
html = html.replace(/\n/g, '<br>')
|
|
return `<p>${html}</p>`
|
|
}
|
|
|
|
return { render }
|
|
}
|