Feedback reply: light Markdown formatting (bold / bullets / heading)
Per Codex: a constrained Markdown-ish composer rather than contenteditable. * goodnews/markup.render_reply_html — escapes everything first, then introduces only a tiny whitelist (**bold**, - bullets, #/##/### headings, paragraphs, line breaks). No links, attributes, inline styles, or raw HTML passthrough. * feedback_replies.message_html column (+ live migration); replies store both the Markdown text and the rendered HTML. * email_send.send_feedback_reply now sends multipart text/plain + text/html (the sanitized render, wrapped in a trusted email template). * Frontend: textarea + a small toolbar (Bold / • List / H) that inserts Markdown; the reply thread renders the server-sanitized HTML. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+16
-4
@@ -63,19 +63,31 @@ def send_feedback(to: str, category: str, message: str, contact: str | None, who
|
||||
send_email(to, subject, text)
|
||||
|
||||
|
||||
def send_feedback_reply(to: str, reply_message: str, original_message: str) -> None:
|
||||
"""Reply to a reader's feedback from the admin inbox (plain text). Quotes
|
||||
def send_feedback_reply(to: str, reply_text: str, reply_html: str | None, original_message: str) -> None:
|
||||
"""Reply to a reader's feedback from the admin inbox. Sends multipart
|
||||
text/plain + text/html (the HTML is the pre-sanitized Markdown render). Quotes
|
||||
their original note for context; exposes no analytics/account details."""
|
||||
subject = "Re: Your Upbeat Bytes feedback"
|
||||
quoted = "\n".join("> " + line for line in (original_message or "").splitlines())
|
||||
text = (
|
||||
f"{reply_message}\n\n"
|
||||
f"{reply_text}\n\n"
|
||||
"—\n"
|
||||
"In reply to your note to Upbeat Bytes:\n"
|
||||
f"{quoted}\n\n"
|
||||
"Thanks for reaching out.\n— Upbeat Bytes\n"
|
||||
)
|
||||
send_email(to, subject, text)
|
||||
body_html = None
|
||||
if reply_html:
|
||||
oq = escape(original_message or "").replace("\n", "<br>")
|
||||
body_html = (
|
||||
'<div style="font-family:-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif;'
|
||||
'color:#16263a;font-size:15px;line-height:1.5">'
|
||||
f"{reply_html}"
|
||||
'<p style="color:#5d6b78;font-size:13px;margin-top:20px">In reply to your note to Upbeat Bytes:</p>'
|
||||
f'<blockquote style="color:#5d6b78;border-left:3px solid #e8e3d8;margin:0;padding-left:12px">{oq}</blockquote>'
|
||||
"<p>Thanks for reaching out.<br>— Upbeat Bytes</p></div>"
|
||||
)
|
||||
send_email(to, subject, text, html=body_html)
|
||||
|
||||
|
||||
def send_magic_link(to: str, link: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user