npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

slackmark

v0.6.2

Published

Compile SlackMark (CommonMark and GFM plus Slack extensions) to Slack Block Kit JSON

Readme

slackmark

SlackMark is the Markdown dialect this compiler understands: CommonMark → GFM → SlackMark. It adds Mermaid charts, math, admonitions, task lists, and mentions to GFM, then compiles the result to Slack Block Kit JSON. Compilation is rich_text-first, capability-gated, and reports structured degradations.

Need a React preview? react-blockkit renders any Block Kit JSON and pairs perfectly with slackmark.

Features

  • SlackMark → Block Kit (rich_text, header, table, data_table, markdown, data_visualization, container, …)
  • Capability profiles (latest, conservative, dated presets)
  • Ordered fallback chains with Degradation records (never silent)
  • Message budgets (50 blocks, table/markdown/chart caps)
  • Mermaid pie / xychart-beta → native charts; other mermaid diagrams → configured renderers or preformatted fallback
  • Display math and non-mermaid code fences → configured renderers or preformatted/code text
  • OOP + constructor DI; convert() convenience for simple use

Quickstart

pnpm add slackmark
import { convert } from "slackmark";

const { blocks, text, degradations, receipts } = await convert("# Hello **Slack**", {
  timeoutMs: 5_000,
});

Advanced (inject fakes / custom adapters):

import { createConverter } from "slackmark";

const converter = createConverter({
  capabilities: "2026-03",
  renderers: [myRenderer],
  uploader: myUploader,
});
const result = await converter.convert(markdown);

API

| Export | Role | | --- | --- | | convert / convertToMessages | Convenience functions (default wiring per call) | | createConverter | Composition root | | SlackMarkConverter | Stateless converter class | | NodeAdapter / Candidate | Extension seams | | ImageRenderer / SlackUploader | Renderer and upload seams | | validateBlocks | Limit validator |

Result shape: { blocks, text, degradations, receipts }. Receipts report external upload effects separately from content fallbacks.

Compat profiles

| Preset | Flags | | --- | --- | | latest (default) | all | | conservative | all flags off | | 2025-02 | + markdownBlock | | 2025-08 | + tableBlock | | 2026-03 | + preformattedLanguage, headerLevel | | 2026-05 | + dataTable | | 2026-06 | + dataVisualization, containerBlock |

Pass a preset name, a flags object, and/or capabilityOverrides.

Renderers & uploads

Built-in adapters cover the mapping matrix. Prepend custom NodeAdapters via createConverter({ adapters }).

No renderer or uploader is enabled by default, so default conversion performs no network I/O. Mermaid fences consult config.renderers after native pie / xychart-beta candidates. Display math and generic code fences consult the same ordered renderer list before their preformatted fallback. Each renderer's canRender method decides which normalized languages it accepts.

Hosted URL renderers compose durable public HTTPS PNG URLs (no network I/O in core); they return null when Slack's 3,000-character image_url limit would be exceeded. Renderer, uploader, and capability-check failures remain scoped to one Markdown node. Attempt failures are buffered while later renderers run: a later success emits no degradation, while an all-failed chain records structured details before text fallback.

Import first-party URL adapters from the dedicated subpath:

import { createConverter } from "slackmark";
import { KrokiRenderer, MermaidInkRenderer } from "slackmark/renderers";

const converter = createConverter({
  renderers: [new MermaidInkRenderer()],
  // or: renderers: [new KrokiRenderer()],
});
  • MermaidInkRenderer emits pako-state PNG URLs for mermaid fences with a non-transparent background by default.
  • KrokiRenderer handles Mermaid and supported diagram fence languages such as d2, dot, and plantuml.
  • CodeCogsRenderer handles display math and katex, latex, math, or tex fences.
  • QuickChartRenderer handles chart, chart.js, chartjs, and quickchart fences.

For local Mermaid and KaTeX PNGs in a Node bot, install slackmark-node and use its resource-owning helper. See the slackmark-node README and the Rasterize content guide, whose lifecycle example preserves both the primary error and a close error.

It reuses one lazy Chromium instance; the uploader lifetime and credentials stay separate. slackmark-node requires Node 22.12+; core remains universal.

Hosted services receive the diagram source encoded in the URL when Slack fetches the image. Treat them as explicit data-egress opt-ins. Each adapter accepts baseUrl for a self-hosted deployment:

const privateRenderers = [
  new KrokiRenderer({ baseUrl: "https://kroki.internal.example" }),
  new MermaidInkRenderer({ baseUrl: "https://mermaid.internal.example" }),
];

Bytes results use a SlackUploader. A missing uploader is deferred while later renderers can recover, then becomes a terminal ConfigurationError only if no renderer succeeds. Upload effects are returned separately in immutable receipts, including effects from failed attempts. The fetch implementation uses Slack's external upload flow:

import { createConverter } from "slackmark";
import { FetchSlackUploader } from "slackmark/slack";

const uploader = new FetchSlackUploader({
  token: slackBotToken,
});

const converter = createConverter({
  renderers: [localBytesRenderer],
  uploader,
});

Inject fetch, sleep, and clock functions for deterministic tests. The Slack token needs files:write. Optional files.info processing polling additionally needs files:read; explicit channelId sharing can create a separate file-share message.

Raw Slack entities

Markdown that already contains Slack mrkdwn tokens — <@U…>, <#C…>, <!here>, <!subteam^S…>, <!date^…> — converts to native rich text elements (no resolvers required). HTML-entity-escaped forms such as &lt;@U123&gt; convert the same way: remark decodes character references before slackmark sees the text. To keep the syntax literal, wrap it in a code span (`<@U123>`).

Optional remark plugins

remark-math and remark-frontmatter are dependencies; enable with enableMath / enableFrontmatter. Display math is parsed when enabled, then offered to configured renderers before preformatted fallback. Single-dollar inline math is a separate opt-in (enableInlineMath): agent prose is far likelier to contain $200/mo than $x$, and reading the span between two dollar signs as math deletes both signs. When it is opted into, inline math stays code-styled text.

License

MIT © Siraj