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

gfm-it

v0.4.2

Published

Render GitHub Flavored Markdown into a complete HTML document.

Readme

gfm-it

Render GitHub Flavored Markdown into a complete HTML document.

The package ships both the renderer and the GFM assets. Use local assets when a server exposes /asset/<key>, and inline assets when the HTML should stand alone.

CLI

# CLI defaults to inline assets, so the output HTML can be opened directly.
gfm-it README.md --title README --output README.html

# SEO metadata.
gfm-it post.md \
  --canonical https://example.com/post \
  --fallback-image true \
  --output post.html

# Use server-hosted assets instead of inline assets.
gfm-it post.md --asset-mode local --asset-base-url /asset/ --output post.html

# Use CDN assets.
gfm-it post.md --asset-mode remote --output post.html

# Use a stylesheet href directly.
gfm-it post.md --asset-mode remote -c https://example.com/hi.css?raw=true --output post.html

# Select a bundled GFM theme. Short aliases such as `github` are accepted.
gfm-it post.md -c github --output post.html

# Markdown front matter `gfm_css` overrides -c/--css when it is valid.

# Read from stdin.
printf '# Hello\n' | gfm-it --title Hello

JavaScript

import { renderMarkdownToHtml } from 'gfm-it';

const html = renderMarkdownToHtml('# Hello', {
  title: 'Hello',
  canonical: 'https://example.com/hello',
  fallbackImage: true,

  // API default: remote. CLI default: inline.
  assetMode: 'remote',
});
const html = renderMarkdownToHtml(markdown, {
  // Self-contained HTML: CSS and JS are inserted as <style> and <script>.
  assetMode: 'inline',
});
const html = renderMarkdownToHtml(markdown, {
  // Compatible with servers that expose packaged assets at /asset/<key>.
  assetMode: 'local',
  assetBaseUrl: '/asset/',

  // Raw HTML insertion points around the generated article.
  slots: {
    headEnd: '<meta name="robots" content="index,follow">',
    bodyStart: '<!-- hint: append ?raw to view the raw file -->',
    articleBefore: '<nav><a href="/">Home</a></nav>',
    articleAfter: '<hr>',
    bodyEnd: '<script>console.log("done")</script>',
  },

  extraCss: '.markdown-body { scroll-margin-top: 2rem; }',
  bodyClass: 'post-page',
  footerHtml: '<a href="/">Home</a>',
});
const html = renderMarkdownToHtml(markdown, {
  // Resolver wins over assetMode and assetBaseUrl.
  resolveAssetUrl(asset) {
    return `/static/gfm/${asset.key}`;
  },
});

Go

package main

import gfmit "github.com/mirtlecn/gfm-it"

func render(markdown string) (string, error) {
    return gfmit.RenderMarkdownToHTML(markdown, gfmit.RenderOptions{
        Title:         "Hello",
        Canonical:     "https://example.com/hello",
        FallbackImage: true,

        // Go API default: remote.
        AssetMode: "remote",
    })
}
html, err := gfmit.RenderMarkdownToHTML(markdown, gfmit.RenderOptions{
    // Match a server route such as /asset/vercel.gfm.css.
    AssetMode:    "local",
    AssetBaseURL: "/asset/",

    Slots: gfmit.RenderSlots{
        HeadEnd:   `<meta name="robots" content="index,follow">`,
        BodyStart: `<!-- hint: append ?raw to view the raw file -->`,
    },
    ExtraCSS:   `.markdown-body { scroll-margin-top: 2rem; }`,
    BodyClass:  "post-page",
    FooterHTML: `<a href="/">Home</a>`,
})
html, err := gfmit.RenderMarkdownToHTML(markdown, gfmit.RenderOptions{
    // Self-contained HTML.
    AssetMode: "inline",
})
html, err := gfmit.RenderMarkdownToHTML(markdown, gfmit.RenderOptions{
    // Resolver wins over AssetMode and AssetBaseURL.
    ResolveAssetURL: func(asset gfmit.Asset) (string, error) {
        return "/static/gfm/" + asset.Key, nil
    },
})

Assets

Files under assets/ are shipped in their source format. Remote mode points at jsDelivr .min.css and .min.js URLs, and embedded/inline assets are minified during the build without rewriting the source files. Asset keys are generated from the source file name, for example assets/github.gfm.css becomes github.gfm.css.

import {
  assets,
  getAsset,
  getAssetPath,
  getAssetContentType,
  getAssetRemoteUrl,
} from 'gfm-it';
import { getEmbeddedAssetContent } from 'gfm-it/embedded';

console.log(getAsset('ravel.gfm.css'));
console.log(getAssetRemoteUrl('gfm-addons.js'));
console.log(getEmbeddedAssetContent('highlight-core.js'));
asset, ok := gfmit.GetAsset("ravel.gfm.css")
content, asset, err := gfmit.ReadAsset("ravel.gfm.css")
embeddedContent, err := gfmit.ReadEmbeddedAssetContent("ravel.gfm.css")
allAssets := gfmit.Assets()

Metadata

---
title: YAML Title
description: Short summary for search previews.
canonical: https://example.com/posts/yaml-title
cover: https://example.com/cover.png
date: 2026-06-10
update: 2026-06-11T10:20:30Z
gfm_css: folio
---

# Visible Heading

Article body.
renderMarkdownToHtml(markdown, {
  // Priority: option title > YAML title > first Markdown heading > empty.
  title: 'Option Title',

  // Priority: option canonical > YAML canonical.
  canonical: 'https://example.com/override',

  // If no YAML cover/image or absolute Markdown image exists,
  // emit a stable grayscale Picsum social image.
  fallbackImage: true,
});

| Output | Source | | --- | --- | | <title> | option title, YAML title, first heading | | canonical / og:url | option canonical, YAML canonical | | description / og:description | YAML description, YAML summary, paragraph/list body text | | og:image / twitter:image | YAML cover, YAML image, first absolute Markdown image, fallback image | | article:published_time | YAML date | | article:modified_time | YAML update | | main CSS | valid YAML gfm_css, then option css |

gfm_css accepts the same CSS choices as remote-mode css: bundled GFM theme short names such as github, folio, and terminal, remote stylesheet URLs ending in .css before any query string, and local stylesheet hrefs such as /theme.css, ./theme.css, ../theme.css, github.gfm.css, or ../css.

If gfm_css is invalid, the renderer ignores it and falls back to the API or CLI css option. Short-name theme values still follow the selected assetMode: remote uses jsDelivr, local uses assetBaseUrl, and inline embeds the minified bundled asset. Href values are emitted as direct stylesheet links.

Options

renderMarkdownToHtml(markdown, {
  title: '',
  canonical: '',
  fallbackImage: false,
  // Valid YAML gfm_css overrides this option.
  // Built-in themes accept short names only: ravel, whitey, newsprint, github, folio, terminal, vercel.
  // Values ending in .css are treated as stylesheet hrefs, not built-in themes.
  // Remote mode also accepts stylesheet hrefs.
  css: 'vercel',
  assetMode: 'remote', // remote | local | inline
  assetBaseUrl: '/asset/',
  resolveAssetUrl: undefined,
  slots: {},
  extraCss: '',
  bodyClass: '',
  footerHtml: '',
});
gfmit.RenderOptions{
    Title:         "",
    Canonical:     "",
    FallbackImage: false,
    // Valid YAML gfm_css overrides this option.
    // Built-in themes accept short names only: ravel, whitey, newsprint, github, folio, terminal, vercel.
    // Values ending in .css are treated as stylesheet hrefs, not built-in themes.
    // Remote mode also accepts stylesheet hrefs.
    CSS:           "vercel",
    AssetMode:     "remote", // remote | local | inline
    AssetBaseURL:  "/asset/",
    ResolveAssetURL: nil,
    Slots:         gfmit.RenderSlots{},
    ExtraCSS:      "",
    BodyClass:     "",
    FooterHTML:    "",
}

Dynamic assets:

| Trigger | Assets | | --- | --- | | always | selected base CSS; gfm-addons.css, gfm-addons.js | | code block | highlight light/dark CSS; Go also injects highlight-core.js | | display math | KaTeX CSS |

Go uses goldmark, GFM, footnotes, GitHub alert callouts, KaTeX, and unsafe raw HTML rendering. The wrapper options match the JavaScript API; parser output is not guaranteed to be byte-for-byte identical.