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

@hartewired/md-to-gdoc

v0.1.0

Published

Turn markdown into a nicely formatted Google Doc. A pure, zero-dependency markdown -> Docs API batchUpdate request builder (does the painful index math for you), plus an optional stateless CLI.

Readme

@hartewired/md-to-gdoc

Turn markdown into a nicely formatted Google Doc.

The Google Docs API is index-based: you insert plain text, then style it by character range — computing every offset by hand, and re-deriving them whenever text shifts. md-to-gdoc does that arithmetic for you. The core is a pure, zero-dependency function that converts markdown into Docs batchUpdate requests; a small CLI is included for the common "markdown file → new doc" case.

Library

npm install @hartewired/md-to-gdoc
import { mdToDoc } from '@hartewired/md-to-gdoc';

const { title, requests, tables } = mdToDoc('# Report\n\nHello **world**.');
// title    -> "Report"
// requests -> Docs API batchUpdate requests (headings, styles, lists, ...)
// tables   -> table specs for a second pass (see "Tables" below)

mdToDoc is transport-agnostic — it never talks to Google. Feed requests to whatever Docs client you already use. With the official googleapis:

import { google } from 'googleapis';
const docsApi = google.docs({ version: 'v1', auth });

const { title, requests } = mdToDoc(markdown);
const { data } = await docsApi.documents.create({ requestBody: { title } });
await docsApi.documents.batchUpdate({
  documentId: data.documentId,
  requestBody: { requests },
});

That's the whole integration for table-free docs. Tables need a short second pass because insertTable rewrites cell indices — see bin/gdoc.js (buildTables) for a reference implementation you can copy.

Exports

  • mdToDoc(markdown, { title? }) → { title, text, requests, tables }
  • parseInline(str) / parseBlocks(markdown) — the underlying parsers
  • splitLargeInserts(requests, maxBytes?) — split an oversized insertText (useful when your transport has an argv/line-length limit, e.g. shelling a CLI)
  • rebaseIndices(node, delta) — shift every index to append into an existing doc

CLI

The package also ships a stateless gdoc command that creates the doc for you.

gdoc notes.md                     # -> prints the new doc's URL
gdoc notes.md --title "Q3 Plan"   # override the title
gdoc notes.md --json              # -> {documentId,url,title}
cat notes.md | gdoc               # read from stdin
gdoc notes.md --doc-id <ID>       # append into an existing doc
gdoc notes.md --dry-run           # print the batchUpdate requests only

Setup

  1. Create an OAuth client (Desktop app) in a Google Cloud project with the Google Docs API enabled. Add http://127.0.0.1 to its authorized redirect URIs.

  2. Authenticate:

    gdoc auth --client-id <ID> --client-secret <SECRET>
    # headless / remote box with no browser:
    gdoc auth --manual --client-id <ID> --client-secret <SECRET>

    This stores a refresh token in ~/.config/md-to-gdoc/config.json (mode 600). Multiple accounts are supported: gdoc auth --account work …, then gdoc notes.md --account work. gdoc accounts lists them.

Credentials can also come from the environment (handy for CI): GDOC_CLIENT_ID, GDOC_CLIENT_SECRET, GDOC_REFRESH_TOKEN.

Supported markdown

Headings (#..######; the first # becomes the doc title with TITLE style), bold / italic / ~~strikethrough~~ / inline code, [links](url), bulleted and numbered lists, fenced code blocks, blockquotes, horizontal rules, and pipe tables (with a bold header row).

Not yet: nested lists, inline markdown inside table cells, images, page breaks.

Design

lib/md-to-docs.js accumulates the whole document as one plain-text string, tracks the offset of every styled run and paragraph, then emits one insertText followed by styling requests that never change the text length — so every index stays valid without reflow bookkeeping. Indices are UTF-16 code units, exactly what the Docs API expects. It is fully unit-tested (npm test).

License

MIT