Shared markdown rendering for comment content.
Comments are authored as markdown in the Leaf composer (which renders with
MDEx); rendering with the same engine and render options on display keeps
the two consistent. Output is sanitised by MDEx's allow-list for XSS
protection. Used by both the public comments component and the admin
moderation page so bold/italics/lists/etc. show formatted instead of raw.
Summary
Functions
Renders a comment's markdown content to sanitized HTML inside a pk-comment-md
block. The .pk-comment-md class (styled by comment_markdown_styles/1)
restores list/block spacing without depending on the @tailwindcss/typography
(prose) plugin being present in the host — render comment_markdown_styles
once on any page that uses this.
One-off <style> block with the .pk-comment-md rules. Render it ONCE per
page that uses comment_markdown/1 (Tailwind's preflight zeroes list/block
margins; this restores them without the typography plugin). Bold/italic render
via <strong>/<em> already.
Renders markdown to sanitised HTML (or escaped text on a parse error). Blank input returns an empty string.
Functions
Renders a comment's markdown content to sanitized HTML inside a pk-comment-md
block. The .pk-comment-md class (styled by comment_markdown_styles/1)
restores list/block spacing without depending on the @tailwindcss/typography
(prose) plugin being present in the host — render comment_markdown_styles
once on any page that uses this.
Named comment_markdown (not markdown) to avoid clashing with core's
PhoenixKitWeb.Components.Core.Markdown.markdown/1, which is imported wherever
use PhoenixKitWeb is in play.
Attributes
content(:string) (required) - The markdown content to render.class(:string) - Additional CSS classes. Defaults to"".compact(:boolean) - Use smaller (text-sm) text for previews. Defaults tofalse.
One-off <style> block with the .pk-comment-md rules. Render it ONCE per
page that uses comment_markdown/1 (Tailwind's preflight zeroes list/block
margins; this restores them without the typography plugin). Bold/italic render
via <strong>/<em> already.
Renders markdown to sanitised HTML (or escaped text on a parse error). Blank input returns an empty string.
Why sanitize: and not a regex pass afterwards
unsafe: true is what lets a comment contain real markdown-adjacent HTML,
and it disables MDEx's own escaping — so everything downstream of it is the
security boundary. That used to be a handful of regexes over the rendered
string, which is a blocklist, and a blocklist over HTML loses:
<script>alert(1)with NO closing tag survived — the pattern required a matching</script>.<a href=javascript:alert(1)>survived — the pattern required the value to be quoted.
Both were verified against the real renderer, and both execute for every
reader of a thread and again in the admin moderation list, which renders the
same component. MDEx's :sanitize is ammonia, an allow-list: unknown tags
and every attribute outside the allowed set are dropped rather than matched
against, and it rewrites rel on links for free. There is no opt-out.