Skip to content
Ferromark

Ferromark / Shared reference

Rendering and Trust

Choose the output policy for the source you accept. Raw HTML recognition and permission to emit that HTML are different decisions.

Defaults depend on the API

IntegrationDefaultFor untrusted Markdown
RustRaw HTML passthroughSet HtmlRendererOptions::sanitize to true
Node.jsEscaped raw HTML and filtered URL schemesKeep renderPolicy: 'untrusted'

Sanitized output escapes raw HTML and filters unsafe link/image URL schemes. The GFM tag filter only neutralizes a narrow list of disallowed tags; it is not an HTML sanitizer. Custom renderer hooks and highlighter HTML are written verbatim and must escape untrusted code, metadata, and attributes themselves.

Specification output and publishing conveniences

CommonMark profiles turn off extra heading IDs, callouts, and fence metadata cleanup. GFM specification profiles additionally select the defined extensions. Rust exposes paired parser/renderer constructors; Node's publishing API offers individual flags and keeps its own defaults.

The explicit CommonMark profile agrees with all 652 examples in the recorded audit. Correctness and compatibility retains corpus scope, oracle exceptions, and known GFM differences. These finite suites do not prove correctness on every possible document. The HTML path captures MDX syntax; the separate JSX path compiles authored documents with optional strict grammar validation. See MDX boundaries for the contracts of each path.

Input limits and migration

Block nesting defaults to 100 levels. Exceeding that limit returns a parse error. Rust callers can configure it; avoid unlimited recursion on untrusted source. Source positions are compact u32 offsets, so the parser addresses just under 4 GB of Markdown. Node.js strings stop far below that; a Uint8Array can reach the limit, and the binding rejects more than 4,294,967,295 bytes with ERR_OUT_OF_RANGE before reading the input. Applications should also bound request sizes and concurrency for their deployment.

V2 was a breaking release from v1. Heading slugs, extension output, site routing, and Rust API signatures differ from v1. The v1-to-v2 migration guide lists changed and removed options. For the breaking changes from v2 to v3, see the v2-to-v3 migration guide.