mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-21 14:18:04 +02:00
Analyseur de texte riche pour les informations adhérents
Sous-ensemble de Markdown — gras, italique, listes, liens, sous-titres — analysé par `src/lib/rich-text.ts` puis rendu en éléments React, jamais en HTML brut : même principe que le journal d'activité. Un éditeur WYSIWYG aurait imposé de stocker du HTML tiers puis de l'assainir, soit une seconde dépendance et une seconde surface d'attaque. Deux rendus, un seul analyseur : `richTextNodes()` pour l'écran, `richTextToEmailHtml()` pour le message. L'aperçu du formulaire passera par le premier, il sera donc fidèle par construction. `safeHttpUrl()` remplace le `webUrl()` privé d'`email-templates.ts` : un lien hors http/https perd sa cible et ne garde que son libellé. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014QsLjRAnuLwivqxCbM4WeP
This commit is contained in:
3 files changed
+487
-10
No files matched your search
@@ -1,3 +1,5 @@
|
||||
import { safeHttpUrl } from "@/lib/rich-text";
|
||||
|
||||
export type EmailBrand = {
|
||||
associationName: string;
|
||||
address?: string;
|
||||
@@ -45,15 +47,6 @@ function lines(value: unknown) {
|
||||
return esc(value).replace(/\r?\n/g, "<br>");
|
||||
}
|
||||
|
||||
function webUrl(value: string) {
|
||||
try {
|
||||
const url = new URL(value);
|
||||
return url.protocol === "http:" || url.protocol === "https:" ? url.href : "";
|
||||
} catch {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function paragraphs(value: string) {
|
||||
return value
|
||||
.split(/\r?\n\s*\r?\n/)
|
||||
@@ -100,7 +93,7 @@ function emailShell({ title, content, baseUrl, brand }: { title: string; content
|
||||
}
|
||||
|
||||
function cta(url: string, label: string) {
|
||||
const safe = webUrl(url);
|
||||
const safe = safeHttpUrl(url);
|
||||
if (!safe || !label) return "";
|
||||
return `<table role="presentation" width="300" cellpadding="0" cellspacing="0" border="0" style="width:300px;border-collapse:collapse;"><tr><td align="center" bgcolor="#2C6FB3" style="background:#2C6FB3;padding:16px 0;border-radius:8px;font-family:Arial,Helvetica,sans-serif;font-size:17px;font-weight:bold;"><a href="${esc(safe)}" target="_blank" style="display:block;color:#FFFFFF;text-decoration:none;">${esc(label)}</a></td></tr></table>`;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user