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). With the built-in pipeline and valid options, unsupported content falls back. Invalid options, a configured renderer returning bytes when no uploader or later successful renderer is available, 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 measured from the start of the call
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 parser, node adapter, plain-text renderer, image renderer, or uploader supplied by your application. Invalid construction shapes fail with ConfigurationError. Runtime behavior depends on the seam: parser and plain-text failures reject as configuration errors, ordinary adapter failures use the document fallback, and ordinary renderer/upload failures follow the renderer fallback chain. Typed configuration and operation errors reject.

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.

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

slackmark exports the conversion API. Its slackmark/renderers and slackmark/slack subpaths expose optional integrations; slackmark-node is a separate package with its own subpaths.

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 uses web-standard APIs and performs no I/O by default. 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.