@@ -4,17 +4,18 @@ use crate::security;
44use crate :: shorturl:: ShortUrlService ;
55use crate :: AppState ;
66
7- /// Convert Markdown to HTML using comrak, with inline styles on `<img>` tags
8- /// so images display properly in both previews and email clients.
9- pub fn render_markdown ( md : & str ) -> String {
7+ /// Convert Markdown to HTML using comrak, absolutize relative image srcs,
8+ /// and add inline styles on `<img>` tags so images display properly in email clients.
9+ pub fn render_markdown ( md : & str , base_url : & str ) -> String {
1010 use comrak:: { markdown_to_html, Options } ;
1111 let mut options = Options :: default ( ) ;
1212 options. extension . strikethrough = true ;
1313 options. extension . table = true ;
1414 options. extension . autolink = true ;
1515 options. render . unsafe_ = true ;
1616 let html = markdown_to_html ( md, & options) ;
17- style_images_for_email ( & html)
17+ let html = style_images_for_email ( & html) ;
18+ absolutize_image_srcs ( & html, base_url)
1819}
1920
2021/// Rewrite relative `src` attributes (e.g. `/uploads/...`) to absolute URLs
@@ -204,10 +205,9 @@ pub async fn send_newsletter(
204205 . map_err ( |e| e. to_string ( ) ) ?,
205206 } ;
206207
207- // Render markdown → HTML, sanitize, then absolutize relative image paths for email clients
208- let content_html = render_markdown ( & markdown_content) ;
208+ // Render markdown → HTML (includes image src absolutization), then sanitize
209+ let content_html = render_markdown ( & markdown_content, & state . config . base_url ) ;
209210 let content_html = sanitize_html ( & content_html) ;
210- let content_html = absolutize_image_srcs ( & content_html, & state. config . base_url ) ;
211211
212212 // Update rendered_html
213213 sqlx:: query ( "UPDATE newsletters SET rendered_html = $1, updated_at = NOW() WHERE id = $2" )
@@ -523,28 +523,28 @@ mod tests {
523523
524524 #[ test]
525525 fn test_render_markdown_basic ( ) {
526- let html = render_markdown ( "# Hello\n \n World" ) ;
526+ let html = render_markdown ( "# Hello\n \n World" , "" ) ;
527527 assert ! ( html. contains( "<h1>Hello</h1>" ) ) ;
528528 assert ! ( html. contains( "<p>World</p>" ) ) ;
529529 }
530530
531531 #[ test]
532532 fn test_render_markdown_links ( ) {
533- let html = render_markdown ( "[COSCUP](https://coscup.org)" ) ;
533+ let html = render_markdown ( "[COSCUP](https://coscup.org)" , "" ) ;
534534 assert ! ( html. contains( "href=\" https://coscup.org\" " ) ) ;
535535 assert ! ( html. contains( "COSCUP" ) ) ;
536536 }
537537
538538 #[ test]
539539 fn test_render_markdown_table ( ) {
540540 let md = "| A | B |\n |---|---|\n | 1 | 2 |" ;
541- let html = render_markdown ( md) ;
541+ let html = render_markdown ( md, "" ) ;
542542 assert ! ( html. contains( "<table>" ) ) ;
543543 }
544544
545545 #[ test]
546546 fn test_render_markdown_strikethrough ( ) {
547- let html = render_markdown ( "~~deleted~~" ) ;
547+ let html = render_markdown ( "~~deleted~~" , "" ) ;
548548 assert ! ( html. contains( "<del>deleted</del>" ) ) ;
549549 }
550550
0 commit comments