# Message rendering — handoff ## Summary Built-in plugins parse and render message bodies: custom markdown (block + inline), HTML sanitization, syntax highlighting, matrix.to links, emoji shortcodes, bad-word filter hooks, and PDF preview support. ## User-facing behavior - Messages render formatted text, code blocks with Prism highlighting - Clickable matrix.to / room links - Custom emoji from packs inline - Spoiler/highlight/color extensions where enabled ## Architecture ``` RenderMessageContent.tsx → react-custom-html-parser.tsx → plugins/markdown/ (block + inline parsers) → plugins/react-prism/ReactPrism.tsx → plugins/emoji.ts, matrix-to.ts, color.ts msgContent.ts — content type detection ``` ## Key files | Path | Role | |------|------| | `cinny/src/app/components/RenderMessageContent.tsx` | Main render entry | | `cinny/src/app/plugins/react-custom-html-parser.tsx` | HTML → React | | `cinny/src/app/plugins/markdown/` | Markdown rules + parsers | | `cinny/src/app/plugins/react-prism/ReactPrism.tsx` | Code highlighting | | `cinny/src/app/plugins/emoji.ts` | Emoji shortcodes | | `cinny/src/app/plugins/matrix-to.ts` | matrix.to link handling | | `cinny/src/app/plugins/bad-words.ts` | Content filter hook | | `cinny/src/app/plugins/color.ts` | Text color | | `cinny/src/app/utils/sanitize.ts` | HTML sanitization | | `cinny/src/app/features/room/msgContent.ts` | Message content helpers | ## Data model None — pure functions over message content JSON. ## Dependencies - `prismjs` (via react-prism) - `pdfjs-dist` wrapper for PDF thumbnails - `millify` for number formatting in embeds ## Integration points - **room-timeline**: all message bodies - **forum**: `forumRichText.ts`, `ForumMessageBody.tsx` - **custom-emoji-packs**: emoji plugin reads pack data - **embed-filters**: separate from body render — URL preview gating ## Testing ### Manual 1. Send markdown: bold, code fence, link. 2. Verify matrix.to link navigates in-app. 3. Custom emoji shortcode renders image. 4. XSS attempt in message — should sanitize. ### Automated - None ## Known issues & gotchas - Markdown rules split block vs inline — order matters in parser - `bad-words.ts` may be no-op depending on config - HTML from other clients may not match Paarrot markdown subset ## Future work - CommonMark test suite - Lazy-load Prism languages ## Related docs - [room-timeline HANDOFF](../room-timeline/HANDOFF.md) - [custom-emoji-packs HANDOFF](../custom-emoji-packs/HANDOFF.md) ## Add your extra things here - `plugins/markdown/block/rules.ts` and `inline/rules.ts` — start here for new syntax - `via-servers.ts` for link join hints