convert()

import { convert, convertToMessages, createConverter } from "slackmark";

function convert(markdown: string, options?: ConvertOptions): Promise<ConversionResult>;
function convertToMessages(
  markdown: string,
  options?: ConvertOptions,
): Promise<ConversionMessagesResult>;
function createConverter(options?: CreateConverterOptions): SlackMarkConverter;
  • convert: markdown in, one message out (blocks, text, degradations, receipts). Markdown never makes it throw: unsupported content falls back. Invalid options, cancellation, and timeouts reject.
  • convertToMessages: same input, but with overflow: "split" long content becomes multiple messages, split between blocks. Without that option it returns a single degraded message. See Long content and splitting.
  • createConverter: builds a reusable, stateless converter with default options; call converter.convert(markdown, perCallOptions?) or converter.convertToMessages(...). Per-call options override the defaults. Prefer this when converting many messages.

Result shapes are documented in ConversionResult.

ConvertOptions

Every option is optional. Content options can be set as createConverter defaults or per call. signal and timeoutMs are per-call only.

OptionTypeDefaultEffect
capabilitiespreset name | flags | partial flags"latest"Which Slack block types the destination supports (presets)
capabilityOverridespartial flagsFlag-level overrides applied on top of capabilities
overflow"degrade" | "split""degrade"Truncate to one message, or split into several (convertToMessages only)
strategy"rich-text-first" | "markdown-block""rich-text-first"Full block mapping, or raw markdown in markdown blocks
renderersImageRenderer[][]Ordered image renderers for any fenced language (guide)
uploaderSlackUploaderUploads bytes-producing renderer output to Slack's files API
signalAbortSignalOptional caller cancellation
timeoutMsnumberRelative operation timeout; converted internally to one absolute collaborator context
enableMathbooleanfalseParse $$…$$ display math and offer it to renderers
enableInlineMathbooleanfalseAlso read $x$ inside a paragraph as math; off so prose keeps its dollar amounts
enableFrontmatterbooleanfalseParse and skip leading YAML/TOML frontmatter (with a degradation)
mentionResolvers{ resolveUser?, resolveChannel? }Resolve bare @handle / #channel to Slack IDs (details)

Bad options fail loudly. createConverter checks its defaults synchronously and throws ConfigurationError; convert and convertToMessages reject with the same error. Only undefined counts as omitted, so convert(md, { overflow: null }) rejects rather than quietly falling back to "degrade".

A collaborator, here and elsewhere in these docs, is a piece you can supply in place of slackmark's own: the markdown parser, extra node adapters, the plain-text renderer, renderers, and the uploader. Their shapes are checked when the converter is built, and a parser or adapter that fails mid-conversion also rejects with ConfigurationError.

Renderers and uploaders behave differently on purpose, because they reach outside the process. A renderer that throws, or returns something the converter cannot use, does not reject the conversion: the failure is recorded as a degradation and the content falls back to text. Puppeteer's LaunchOptions belongs to slackmark-node, which passes it through untouched.

CreateConverterOptions

createConverter accepts everything above plus injection seams. These exist only at construction and cannot be passed per call:

OptionTypeEffect
adaptersNodeAdapter[]Custom node adapters, consulted before the built-ins
parserMarkdownParserReplace the default remark-based markdown parser
plainTextPlainTextRendererReplace the notification-text renderer

These are extension and testing seams; typical use never needs them.

Subpath exports

The package entry exports the conversion API; two optional subpaths carry network-facing implementations:

Import pathExports
slackmarkconvert, convertToMessages, createConverter, validateBlocks, CAPABILITY_PRESETS, resolveCapabilities, all public types
slackmark/renderersHosted URL renderers: Mermaid Ink, Kroki (Mermaid and other diagrams), CodeCogs (math), and QuickChart (Chart.js)
slackmark/slackFetchSlackUploader, the Slack external-upload flow for bytes-producing renderers
slackmark-nodeHigh-level Node converter, operation types, and public errors (guide)
slackmark-node/renderersBuilt-in Mermaid and KaTeX byte renderers
slackmark-node/puppeteerAdvanced Puppeteer runtime, launcher, and local asset loaders

Deep imports (slackmark/dist/...) are unsupported.

Runtime support

slackmark is universal JavaScript: no Node built-ins, no Buffer, no process, no I/O in core. It runs on Cloudflare Workers, Bun, Deno, and Node ^20.19.0 || >=22.12.0. Default conversion is deterministic: identical input and options produce byte-identical output. With injected collaborators (custom parsers, adapters, renderers, uploaders, mention resolvers), the output is only as deterministic as they are.

slackmark-node is a separate Node.js 22.12+ package because Chromium, filesystem access, and browser-process lifecycle do not belong in universal core.