Svelte 5 components and Markdown helpers for rendering Typst as SVG.
- Svelte
>= 5.36 - Svelte async rendering enabled:
compilerOptions.experimental.async = true - Vite/SvelteKit-compatible asset handling for browser WASM imports
// svelte.config.jsexportdefault{compilerOptions: {experimental: {async: true}}};pnpm add typlete<scriptlang="ts">import { TypstInline, TypstBlock } from'typlete';</script>
<p>
Inline formula: <TypstInlinesource="integral_0^1 x^2 dif x" />
</p>
<TypstBlocksource="sum_(i=1)^n i = (n(n+1)) / 2" />source is Typst math by default. Typlete wraps math input in Typst math delimiters and escapes delimiter-breaking characters ($ and #) before compiling. Do not include outer $...$; pass the formula body.
The implicit foreground of inline SVG rendered by Typlete inherits the surrounding CSS color, just like normal text.
<pclass="secondary">
Energy: <TypstInlinesource="E = m c^2" />
</p>
<style>.secondary {color: var(--text-secondary); }</style>This also follows normal CSS state changes such as :hover, disabled states, theme classes, and inherited custom properties. No formula-specific color prop is required.
Math construction strokes inherit the same color too, including fraction bars, radical bars, overlines, and underlines.
Explicit Typst text colors still take precedence and are preserved in the generated SVG:
<TypstInlinesource="alpha + beta"preamble="#set text(fill: red)" />Color inheritance applies when the SVG is embedded inline, including the Svelte components, the server helper when its SVG is inserted inline, and Markdown output: 'html'. SVG used as an external image (output: 'markdown-image', output: 'asset', or a normal <img>) cannot inherit color from the surrounding HTML document.
Use inputMode="raw" for full Typst markup fragments that should not be wrapped as math. Raw mode passes the source to Typst unchanged, so user-controlled raw input needs separate policy around allowed Typst features and assets.
<TypstBlockinputMode="raw"source={'#rect(radius: 6pt, inset: 10pt)[#strong[Raw Typst]]'} /><!-- math mode: Typlete wraps source in Typst math -->
<TypstInlinesource="alpha + beta" />
<!-- raw mode: Typlete passes source to Typst unchanged -->
<TypstInlineinputMode="raw"source={'$alpha + beta$'} />inputMode="markup" is accepted as a compatibility alias for raw.
Typst, TypstInline, and TypstBlock support these common props:
typeTypstMode='inline'|'block';typeTypstInputMode='math'|'raw'|'markup';typeTypstSvgSanitizer=(svg: string)=>string;
source?: string;
inputMode?: TypstInputMode;
preamble?: string;
textSize?: string;
pageMargin?: string;
cache?: boolean;
sanitize?: TypstSvgSanitizer;
ariaLabel?: string;
title?: string;
loadingLabel?: string;
throwOnError?: boolean;
errorMode?: 'badge'|'none';class?: string;Typst also accepts mode. TypstInline and TypstBlock set mode automatically.
During SSR/build, Typlete renders SVG on the server. After hydration, the browser keeps the server-rendered SVG and loads the Typst WASM runtime only when the formula has to be rendered again on the client.
Typlete ships its own copies of the compiler/renderer WASM modules and the default Typst text font set inside the package. Browser builds emit those files as application-local assets; SSR reads the same installed Typlete assets directly from disk and passes their bytes to the Typst runtime. Normal formula rendering therefore does not fetch runtime assets from a CDN, depend on transitive-package layout, or require consumers to copy WASM/fonts manually.
Raw Typst that explicitly imports external Typst packages can still perform network access according to the underlying Typst package registry. That is separate from Typlete's own runtime assets.
By default, render failures keep the last successful SVG visible and show a small error badge.
<TypstBlocksource={formula} errorMode="badge" />
<TypstBlocksource={formula} errorMode="none" />Use throwOnError={true} when server-side render failures should fail the request/build instead of being converted to component state.
import{renderTypstSvgServer}from'typlete/server';constsvg=awaitrenderTypstSvgServer({source: 'integral_0^1 x^2 dif x',mode: 'block',inputMode: 'math',preamble: '',textSize: '11pt',pageMargin: '0pt',cache: true});Typlete only renders namespaced Typlete fences. Normal typst fences stay normal Markdown code blocks, so documentation can show Typst source without triggering rendering.
Raw Typst render block:
```typlete-typst#set text(size: 12pt)#rect[hello]```Math render block. The content is treated as a formula body; delimiter-breaking $ and # characters are escaped before Typst compiles it:
```typlete-mathsum_(i=1)^n i = (n(n+1)) / 2```Accepted render fence names:
typlete -> raw Typst render block
typlete raw -> raw Typst render block
typlete typst -> raw Typst render block
typlete-typst -> raw Typst render block
typlete-raw -> raw Typst render block
typlete math -> math render block
typlete-math -> math render block
typlete-typst-math -> math render blockTypst source code remains source code:
```typst#set text(size: 12pt)#rect[hello]```For inline formulas in MDsveX, use the Svelte component directly. The same math escaping applies:
The value is <TypstInlinesource="alpha + beta" />.import{transformTypleteMarkdown}from'typlete/markdown';constoutput=awaittransformTypleteMarkdown(markdown,{output: 'component'});Output modes:
typeTypleteMarkdownOutput='component'|'html'|'markdown-image'|'asset';Best for MDsveX/Svelte-aware Markdown pipelines.
awaittransformTypleteMarkdown(markdown,{output: 'component'});Produces Svelte component tags:
<TypstBlocksource={'#rect[hello]'} inputMode="raw" />
<TypstBlocksource={'alpha + beta'} />Best for renderers that accept raw HTML/SVG.
awaittransformTypleteMarkdown(markdown,{output: 'html'});This renders SVG immediately and inserts it into the Markdown output.
Best for renderers that do not support raw HTML but accept Markdown images.
awaittransformTypleteMarkdown(markdown,{output: 'markdown-image'});This renders SVG and inserts it as a data:image/svg+xml Markdown image.
Best for static sites.
awaittransformTypleteMarkdown(markdown,{output: 'asset',assetDir: 'static/typlete',assetBaseUrl: '/typlete'});This writes SVG files to assetDir and inserts normal Markdown image links.
Run the Typlete preprocessor before MDsveX so namespaced Typlete render fences are converted to Svelte component tags before MDsveX compiles the document.
// svelte.config.jsimportadapterfrom'@sveltejs/adapter-auto';import{mdsvex}from'mdsvex';import{createTypstMdsvexPreprocessor}from'typlete/markdown';constconfig={extensions: ['.svelte','.svx','.md'],preprocess: [createTypstMdsvexPreprocessor({output: 'component'}),mdsvex({extensions: ['.svx','.md']})],compilerOptions: {experimental: {async: true}},kit: {adapter: adapter()}};exportdefaultconfig;For output: 'component', the preprocessor injects this import when a document contains a rendered Typst fence:
<scriptlang="ts">import { TypstInline, TypstBlock } from'typlete';</script>Disable injection only if another MDsveX hook already imports the components:
createTypstMdsvexPreprocessor({output: 'component',injectComponentImports: false});Markdown helpers accept the same render options as component/server rendering:
awaittransformTypleteMarkdown(markdown,{output: 'asset',assetDir: 'static/typlete',assetBaseUrl: '/typlete',preamble: '',textSize: '11pt',pageMargin: '0pt',cache: true});Typlete inserts compiler-produced SVG inline. By default it strips embedded SVG <script> tags and common script-like SVG attributes from that output. This is output-level defense-in-depth, not a sandbox for arbitrary raw Typst input or external assets. For stricter SVG sanitizing, pass a sanitizer.
DOMPurify is optional:
import{createDomPurifySvgSanitizer}from'typlete/sanitizers/dompurify';constsanitize=awaitcreateDomPurifySvgSanitizer();Server-side DOMPurify requires both dompurify and jsdom:
import{createServerDomPurifySvgSanitizer}from'typlete/server/dompurify';constsanitize=awaitcreateServerDomPurifySvgSanitizer();- Component SSR depends on Svelte experimental async rendering.
- Plain
typstfences are never render instructions; usetyplete-typst,typlete-raw, ortyplete-mathwhen Markdown should render Typst. - Math mode and
typlete-mathescape$and#before wrapping the source in Typst math delimiters. Raw mode andpreambleare passed to Typst unchanged. - CSS text-color inheritance requires inline SVG. SVG loaded through
<img>, includingmarkdown-imageandassetMarkdown output, does not inherit the parent document'scolor. - Server rendering temporarily guards Typst runtime fetches so SvelteKit does not track external runtime fetches during SSR.
html,markdown-image, andassetoutput modes pre-render SVG immediately and are not reactive on the client.