Rendering articles (ArticleContent)
A published article’s body is plain Markdown (article.markdown). <ArticleContent> renders it to sanitized HTML — GFM on, HTML sanitized — the same contract as @ghostwritr/react and @ghostwritr/vue. It renders the result with {@html}, runs synchronously, and so works anywhere Svelte 5 runs: SvelteKit SSR, prerendered routes, and the browser (SPA).
The renderer is a separate, opt-in entry — it keeps the Markdown dependencies out of data-only consumers:
import { ArticleContent } from "@ghostwritr/svelte/article-content";Pass the article’s markdown. With no class it renders a bare <div> wrapper; pass class to apply prose/Tailwind:
<script lang="ts"> import { ArticleHead } from "@ghostwritr/svelte"; import { ArticleContent } from "@ghostwritr/svelte/article-content"; let { data } = $props();</script>
<ArticleHead article={data.article} siteName="Acme" />
<article> <h1>{data.article.title}</h1> <ArticleContent markdown={data.article.markdown} class="prose" /></article>The data comes from a server load that fetched the article keylessly — see the quickstart.
| Prop | Type | Default | Effect |
|---|---|---|---|
markdown | string | — (required) | The article’s Markdown body. |
class | string | undefined | Wrapper class on the <div> — apply prose/Tailwind here. |
remarkPlugins | PluggableList | undefined | Extra remark plugins, appended after the built-in remark-gfm. |
rehypePlugins | PluggableList | undefined | Extra rehype plugins, appended after the built-in rehype-sanitize. |
The built-ins always apply; your plugins run after them in the same pipeline.
<ArticleContent markdown={data.article.markdown} class="prose" remarkPlugins={[/* appended after remark-gfm */]} rehypePlugins={[/* appended after rehype-sanitize — trusted */]}/>The renderMarkdown helper
Section titled “The renderMarkdown helper”<ArticleContent> is a thin wrapper over renderMarkdown — the underlying synchronous Markdown → sanitized-HTML function. Reach for it directly when you need the HTML string itself (an RSS body, an email, an {@html} binding you control):
import { renderMarkdown } from "@ghostwritr/svelte/article-content";
const html = renderMarkdown(article.markdown, { remarkPlugins: [/* appended after remark-gfm */], rehypePlugins: [/* appended after rehype-sanitize — trusted */],});renderMarkdown(markdown, opts?) returns a string. It applies the same GFM + sanitize built-ins, and appends your remarkPlugins / rehypePlugins after them — identical to the component, including the post-sanitize ordering. See The article shape for what article.markdown contains.