@molecule/app-markdown
Core interface · markdown · App (browser) · v1.0.2 · Apache-2.0
Markdown rendering core interface for molecule.dev.
npm install @molecule/app-markdownHow it works
@molecule/app-markdown is the markdown core interface on the app (browser) side: the API your app calls, with no vendor inside.
Choose the implementation by bonding one of its 2 providers: @molecule/app-markdown-marked, @molecule/app-markdown-react-markdown.
import { requireProvider, setProvider } from '@molecule/app-markdown'
import { provider } from '@molecule/app-markdown-react-markdown'
setProvider(provider) // once, at startup (bonds.ts)
const result = requireProvider().render('# Hello World', { gfm: true })
console.log(result.html) // sanitized HTML stringProviders (2): @molecule/app-markdown-marked, @molecule/app-markdown-react-markdown
Works with: @molecule/app-bond
Live demos
Running apps built with Molecule that install this package — open the app or study the template.
Reference
Markdown rendering core interface for molecule.dev.
Provides a standardized API for rendering markdown content into HTML,
with support for GFM and table of contents extraction.
Bond a provider (e.g. @molecule/app-markdown-react-markdown) to supply
the concrete implementation.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import { requireProvider, setProvider } from '@molecule/app-markdown'
import { provider } from '@molecule/app-markdown-react-markdown'
setProvider(provider) // once, at startup (bonds.ts)
const result = requireProvider().render('# Hello World', { gfm: true })
console.log(result.html) // sanitized HTML string
Type
core
Installation
npm install @molecule/app-markdown @molecule/app-bond
API
Interfaces
TocEntry
Table of contents entry extracted from markdown headings.
interface TocEntry {
/** Unique identifier for the heading (slug). */
id: string
/** Text content of the heading. */
text: string
/** Heading level (1-6). */
level: number
}
RenderedMarkdown
Result of rendering markdown content.
interface RenderedMarkdown {
/** The rendered HTML string. */
html: string
/** Optional table of contents extracted from headings. */
toc?: TocEntry[]
}
MarkdownOptions
Options for markdown rendering.
interface MarkdownOptions {
/** Whether to sanitize the rendered HTML to prevent XSS. Defaults to `true`. */
sanitize?: boolean
/** Whether to enable GitHub Flavored Markdown extensions. Defaults to `true`. */
gfm?: boolean
/** Whether to convert line breaks to `<br>` elements. Defaults to `false`. */
breaks?: boolean
/** Custom component overrides keyed by HTML element name. */
components?: Record<string, unknown>
/** Target attribute for rendered links. */
linkTarget?: '_blank' | '_self'
}
MarkdownProvider
Markdown rendering provider interface.
All markdown providers must implement this interface to render markdown strings into HTML output with optional features.
interface MarkdownProvider {
/** Provider name identifier. */
readonly name: string
/**
* Renders a markdown string into HTML.
*
* @param markdown - The markdown source string to render.
* @param options - Optional rendering configuration.
* @returns The rendered HTML and optional table of contents.
*/
render(markdown: string, options?: MarkdownOptions): RenderedMarkdown
}
Functions
setProvider(provider)
Registers a markdown provider as the active singleton.
function setProvider(provider: MarkdownProvider): void
provider— The markdown provider implementation to bond.
getProvider()
Retrieves the bonded markdown provider, or null if none is bonded.
function getProvider(): MarkdownProvider | null
Returns: The active markdown provider, or null.
hasProvider()
Checks whether a markdown provider has been bonded.
function hasProvider(): boolean
Returns: true if a markdown provider is available.
requireProvider()
Retrieves the bonded markdown provider, throwing if none is configured.
function requireProvider(): MarkdownProvider
Returns: The active markdown provider.
Available Providers
| Provider | Package |
|---|---|
| marked | @molecule/app-markdown-marked |
| react-markdown | @molecule/app-markdown-react-markdown |
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1
Runtime Dependencies
-
@molecule/app-bond -
Wire a bond at startup —
requireProviderthrows untilsetProvider(provider)has been called. -
sanitizedefaults totrueand is the XSS gate. The result is an HTML STRING you inject via your framework's raw-HTML mechanism — that is only safe because it was sanitized. NEVER passsanitize: falsefor user-supplied or model-generated markdown (chat replies, comments, notes); reserve it for fully trusted, app-authored content. -
Options are per-call (
gfm,breaks,linkTarget);result.toccarries extracted headings when the provider supports it. Syntax highlighting is a provider concern — e.g. the react-markdown bond wires a rehype highlighter via itsrehypePluginsconfig rather than a generic option.
E2E Tests
Integration checklist — drive the real UI (live preview, no mocks), adapt each item to this app's actual screens/flows, and check every box off one by one. A box you can't check is an integration bug to fix — not a skip:
- Common markdown renders as real HTML wherever the app shows it (chat
reply, comment, note, README preview):
#..######become<h1>..<h6>,**bold**a<strong>,*italic*an<em>,-/1.lists become<ul>/<ol>of<li>,[text](url)an<a>anchor, and a fenced code block a<pre><code>— not the raw*/backticks shown as literal text. - GFM extras render when enabled (
gfm, default on): a pipe table| a | b |becomes a real<table>with header + rows, andan<img>. - The output tracks the source: editing the markdown updates the preview
live — change a heading's text and its
<h#>updates; add a list item and a new<li>appears. No stale or one-shot render. - SECURITY (XSS) — user- or model-supplied markdown is sanitized
(
sanitize, default on, the XSS gate): markdown containing a raw<script>alert(1)</script>, an<img src=x onerror=alert(1)>, or a[click](javascript:alert(1))link must NOT execute and must NOT produce active markup — the script is stripped, theonerroris gone, and the link'shrefis neutralized. Verify in the browser: no alert fires, and DevTools shows no<script>,onerror, orjavascript:in the rendered DOM. Never render untrusted content withsanitize: false. - Malformed markdown degrades gracefully — an unclosed
**, a broken[link](, or a half-open code fence renders as readable text and never throws, blanks the view, or breaks the surrounding page.