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

@gramdown/core

v1.0.0

Published

The pure, I/O-free engine that turns a Grammarly .docx export into clean, GitHub-Flavored Markdown.

Readme

@gramdown/core

The conversion engine behind gramdown: it turns the .docx file Grammarly hands you when you export a document into clean, GitHub-Flavored Markdown.

It is built for that one file. A Grammarly export has a handful of specific quirks: code set in a plain monospace font with no language, links that arrive underlined, indentation made of invisible characters. This package is designed around them rather than trying to be a general-purpose .docx converter.

It is also pure and I/O-free: no fs, no paths, no process. The same call works in Node, in a bundler and in a Web Worker. The gramdown command and the browser converter on the website are both wrappers around it.

Converting a file on your own machine? Install gramdown instead: it is the command line tool, and this is the library underneath it.

Install

npm install @gramdown/core

Use

import { convert } from "@gramdown/core";

const bytes = new Uint8Array(await file.arrayBuffer());
const markdown = await convert(bytes);

convert(bytes, options?) takes the raw bytes of a Grammarly .docx export and resolves to a Markdown string. In Node, readFile already gives you something convert accepts.

It throws InvalidDocxError when the input is not a readable .docx: the bytes are empty, the archive cannot be opened, or it is not a Word document. Nothing else is thrown; a successful parse always resolves, warnings and all.

Options

| Option | Type | What it does | | --------------- | --------------------------- | ---------------------------------------------------------------------------------------------------- | | guessLanguage | LanguageGuesser | Called with each code block's text to produce a fence info string. Unset means unlabelled fences. | | onWarning | (warning: string) => void | Receives every warning raised while reading the document (an unrecognised style, a dropped element). |

Guessing code-fence languages

Grammarly records no language anywhere in the .docx, so there is nothing to recover; a language can only be guessed. A ready-made guesser ships as a separate subpath export, so callers who don't want it don't pay for its dependency:

import { convert } from "@gramdown/core";
import { languageGuesser } from "@gramdown/core/guess-lang";

const markdown = await convert(bytes, { guessLanguage: languageGuesser });

It is a heuristic: reliable for things like JSON and shell, shakier on JavaScript-vs-TypeScript, and it always needs a human pass. Pass your own (code: string) => string | undefined if you'd rather guess a different way, or leave the option unset and get bare fences.

Documentation

  • convert() API reference: every option, error and export, in full.
  • How it works: what a Grammarly export actually looks like, the four stages of the conversion, and the limitations that come with them.
  • gramdown.tobythe.dev: the command line tool, the standalone binaries, and a converter that runs in your browser.

License

ISC. See LICENSE.md.