Skip to content

API Reference ​

renderMarkdown ​

ts
function renderMarkdown(
  markdown: string,
  options?: RenderMarkdownOptions
): Promise<RenderPage[]>

Parses markdown and renders it into one or more pages.

Parameters ​

ParameterTypeDescription
markdownstringThe Markdown source text to render
optionsRenderMarkdownOptionsOptional render configuration

Returns ​

Promise<RenderPage[]> — an array of rendered pages, one entry per page.

Example ​

ts
import { renderMarkdown } from 'marknative'

const pages = await renderMarkdown('# Hello\n\nWorld.')

for (const page of pages) {
  if (page.format === 'png') {
    // page.data is a Buffer
  }
}

Rendered output:

API overview rendered output


RenderMarkdownOptions ​

ts
type RenderMarkdownOptions = {
  format?: 'png' | 'svg'
  singlePage?: boolean
  theme?: BuiltInThemeName | ThemeOverrides
  scale?: number
  painter?: Painter
  codeHighlighting?: {
    theme?: string  // Shiki theme name — auto-detected from page background if omitted
  }
}

Properties ​

format ​

Type: 'png' | 'svg'
Default: 'png'

Output format for each rendered page.

  • 'png' — raster PNG image; page.data is a Buffer
  • 'svg' — vector SVG; page.data is a string

singlePage ​

Type: boolean
Default: false

When true, renders all content into a single image instead of paginating across multiple fixed-height pages. The image height adapts to the content and is capped at MAX_SINGLE_PAGE_HEIGHT.

theme ​

Type: BuiltInThemeName | ThemeOverrides
Default: defaultTheme

Controls all visual properties. Accepts either:

ts
// Built-in name
await renderMarkdown(md, { theme: 'dracula' })

// Partial override
await renderMarkdown(md, { theme: { colors: { background: '#000' } } })

scale ​

Type: number
Default: 2
Applies to: PNG output only

Pixel density multiplier. The logical page width/height from the active theme are multiplied by this value to determine the physical canvas resolution. Higher values produce sharper images at the cost of larger files and longer encode times (PNG compression scales with pixel count).

ts
await renderMarkdown(md, { scale: 1 })   // ~29 ms — preview
await renderMarkdown(md, { scale: 2 })   // ~99 ms — retina (default)
await renderMarkdown(md, { scale: 3 })   // ~214 ms — print

codeHighlighting ​

Type: { theme?: string }
Default: auto-detected from page background luminance

Controls syntax highlighting for fenced code blocks. Highlighting is powered by Shiki and runs server-side before layout.

  • theme — any Shiki-supported theme name (e.g. 'github-dark', 'nord', 'one-dark-pro', 'dracula'). When omitted, the theme is auto-selected: light page backgrounds use 'github-light', dark page backgrounds use 'github-dark'.
  • Code blocks with an unknown or missing language tag fall back to plain monochrome text — no codeToken runs are produced.
ts
// Auto-detection: light page → github-light
const pages = await renderMarkdown(md)

// Auto-detection: dark page → github-dark
const pages = await renderMarkdown(md, { theme: 'dark' })

// Explicit override
const pages = await renderMarkdown(md, {
  theme: 'nord',
  codeHighlighting: { theme: 'one-dark-pro' },
})

painter ​

Type: Painter
Default: internal skia-canvas painter

Advanced: supply a custom paint backend. Intended for library integrators and testing.


RenderPage ​

ts
type RenderPage =
  | { format: 'png'; data: Buffer; page: PaintPage }
  | { format: 'svg'; data: string; page: PaintPage }

A discriminated union based on format.

Properties ​

PropertyTypeDescription
format'png' | 'svg'The output format of this page
dataBuffer | stringThe rendered image data
pagePaintPageInternal paint-layer page descriptor

Example ​

ts
const pages = await renderMarkdown(markdown, { format: 'png' })

for (const [i, page] of pages.entries()) {
  if (page.format === 'png') {
    writeFileSync(`page-${i + 1}.png`, page.data)
  }
}

MAX_SINGLE_PAGE_HEIGHT ​

ts
const MAX_SINGLE_PAGE_HEIGHT: number // 16384

The maximum height (in CSS pixels) of a single-page render. Content beyond this height is clipped. Exported for consumers that need to check or display the limit.

ts
import { MAX_SINGLE_PAGE_HEIGHT } from 'marknative'

console.log(MAX_SINGLE_PAGE_HEIGHT) // 16384

parseMarkdown ​

ts
function parseMarkdown(markdown: string): MarkdownDocument

Low-level: parse Markdown source text into the internal MarkdownDocument AST. Useful for inspection or custom processing pipelines.


defaultTheme ​

ts
const defaultTheme: Theme

The built-in default theme. Page size is 1080 × 1440 px (portrait card ratio). Exported for use as a base with mergeTheme.

ts
import { defaultTheme } from 'marknative'

console.log(defaultTheme.page)
// { width: 1080, height: 1440, margin: { top: 80, right: 72, bottom: 80, left: 72 } }

mergeTheme ​

ts
function mergeTheme(base: Theme, overrides: ThemeOverrides): Theme

Merge a partial theme override onto a base theme. Each nested object (page, typography, blocks, colors) is merged shallowly at its own level — you only need to supply the keys you want to change.

ts
import { mergeTheme, defaultTheme, getBuiltInTheme } from 'marknative'

// Build on defaultTheme
const myTheme = mergeTheme(defaultTheme, {
  page: { width: 800 },
  colors: { background: '#1e1e2e', text: '#cdd6f4' },
})

// Build on a built-in theme
const customNord = mergeTheme(getBuiltInTheme('nord'), {
  colors: { link: '#ff6b6b' },
})

getBuiltInTheme ​

ts
function getBuiltInTheme(name: BuiltInThemeName): Theme

Return a built-in theme by name. Throws if the name is unknown.

ts
import { getBuiltInTheme } from 'marknative'

const theme = getBuiltInTheme('dark')
console.log(theme.colors.background) // '#1e1e2e'

resolveTheme ​

ts
function resolveTheme(theme?: BuiltInThemeName | ThemeOverrides): Theme

Resolve a theme option value into a fully populated Theme:

  • undefined → defaultTheme
  • BuiltInThemeName string → the named built-in theme
  • ThemeOverrides object → merged onto defaultTheme

This is the same resolution that renderMarkdown performs internally.


isBuiltInThemeName ​

ts
function isBuiltInThemeName(value: string): value is BuiltInThemeName

Type-guard that checks whether a string is a valid built-in theme name.

ts
import { isBuiltInThemeName } from 'marknative'

isBuiltInThemeName('dark')    // true
isBuiltInThemeName('custom')  // false

BUILT_IN_THEME_NAMES ​

ts
const BUILT_IN_THEME_NAMES: readonly BuiltInThemeName[]

A read-only tuple of all built-in theme name strings, in registration order.

ts
import { BUILT_IN_THEME_NAMES } from 'marknative'

console.log(BUILT_IN_THEME_NAMES)
// ['default', 'github', 'solarized', 'sepia', 'rose',
//  'dark', 'nord', 'dracula', 'ocean', 'forest']

BuiltInThemeName ​

ts
type BuiltInThemeName =
  | 'default' | 'github' | 'solarized' | 'sepia' | 'rose'
  | 'dark' | 'nord' | 'dracula' | 'ocean' | 'forest'

Union type of all valid built-in theme name strings.


Theme ​

ts
type Theme = {
  page: {
    width: number
    height: number
    margin: { top: number; right: number; bottom: number; left: number }
  }
  typography: {
    h1: TypographyStyle
    h2: TypographyStyle
    h3: TypographyStyle
    h4: TypographyStyle  // also used for H5 and H6
    body: TypographyStyle
    code: TypographyStyle
  }
  blocks: {
    paragraph: { marginBottom: number }
    heading:   { marginTop: number; marginBottom: number }
    list:      { marginBottom: number; itemGap: number; indent: number }
    code:      { marginBottom: number; padding: number }
    quote:     { marginBottom: number; padding: number }
    table:     { marginBottom: number; cellPadding: number }
    image:     { marginBottom: number }
  }
  colors: ThemeColors
}

Fully-populated theme object. All fields are required. Use ThemeOverrides when you only want to override a subset.


ThemeOverrides ​

ts
type ThemeOverrides = {
  page?: Partial<{ width: number; height: number }> & {
    margin?: Partial<{ top: number; right: number; bottom: number; left: number }>
  }
  typography?: {
    h1?: Partial<TypographyStyle>
    h2?: Partial<TypographyStyle>
    h3?: Partial<TypographyStyle>
    h4?: Partial<TypographyStyle>
    body?: Partial<TypographyStyle>
    code?: Partial<TypographyStyle>
  }
  blocks?: { [K in keyof Theme['blocks']]?: Partial<Theme['blocks'][K]> }
  colors?: Partial<ThemeColors>
}

Every field is optional. Missing fields inherit from the base theme (usually defaultTheme). Pass this as the theme option to renderMarkdown, or as the second argument to mergeTheme.


ThemeColors ​

ts
type ThemeColors = {
  background: string
  backgroundGradient?: GradientFill
  text: string
  link: string
  mutedText: string
  border: string
  subtleBorder: string
  codeBackground: string
  quoteBackground: string
  quoteBorder: string
  imageBackground: string
  imageAccent: string
  checkboxChecked: string
  checkboxCheckedMark: string
  checkboxUnchecked: string
  tableHeaderBackground?: string  // defaults to codeBackground
}

All color values are CSS color strings (hex, rgb, hsl, named colors). See the Themes guide for a description of each token.


GradientFill ​

ts
type GradientFill = LinearGradientFill | RadialGradientFill

type LinearGradientFill = {
  type: 'linear'
  angle?: number   // degrees; 0 = top→bottom (default), 90 = left→right
  stops: ColorStop[]
}

type RadialGradientFill = {
  type: 'radial'
  stops: ColorStop[]  // radiates from the page centre outward
}

type ColorStop = {
  offset: number  // 0–1
  color: string
}

Set on ThemeColors.backgroundGradient to apply a gradient page background. See the gradient section of the Themes guide for examples.


TypographyStyle ​

ts
type TypographyStyle = {
  font: string        // CSS font shorthand, e.g. 'bold 52px sans-serif'
  lineHeight: number  // line height in pixels
}

Released under the MIT License.