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

@peaceroad/markdown-it-renderer-fence

v0.8.0

Published

A markdown-it fence renderer with code/samp output, line features, Custom Highlight API support, and optional themes.

Readme

p7d-markdown-it-renderer-fence

A markdown-it fence renderer for safer <pre><code> / <pre><samp> output, line features, optional syntax highlighting, and advanced Custom Highlight API integration.

Default mode is markup. Custom Highlight API mode is available for advanced browser-runtime highlighting.

Install

npm i @peaceroad/markdown-it-renderer-fence markdown-it markdown-it-attrs

Install a highlighter separately when you need syntax highlighting, for example highlight.js or shiki.

Quick Start (Markup Mode)

import MarkdownIt from 'markdown-it'
import markdownItAttrs from 'markdown-it-attrs'
import hljs from 'highlight.js'
import rendererFence from '@peaceroad/markdown-it-renderer-fence/markup-highlight'

const md = MarkdownIt({
  html: true,
  langPrefix: 'language-',
  highlight: (code, lang) => {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(code, { language: lang }).value
      } catch (e) {}
    }
    return md.utils.escapeHtml(code)
  },
})
  .use(markdownItAttrs)
  .use(rendererFence)

Shiki in Markup Mode

Preload the languages you render, then return Shiki HTML from md.options.highlight.

import MarkdownIt from 'markdown-it'
import markdownItAttrs from 'markdown-it-attrs'
import { createHighlighter } from 'shiki'
import rendererFence from '@peaceroad/markdown-it-renderer-fence/markup-highlight'

const highlighter = await createHighlighter({
  themes: ['github-light'],
  langs: ['javascript', 'typescript', 'json', 'text'],
})

const md = MarkdownIt({
  html: true,
  langPrefix: 'language-',
  highlight: (code, lang) => {
    try {
      return highlighter.codeToHtml(code, { lang: lang || 'text', theme: 'github-light' })
    } catch (e) {
      return md.utils.escapeHtml(code)
    }
  },
})
  .use(markdownItAttrs)
  .use(rendererFence)

Entry Points

| Import | Purpose | | --- | --- | | @peaceroad/markdown-it-renderer-fence | compatibility dispatcher; highlightRenderer selects mode | | @peaceroad/markdown-it-renderer-fence/markup-highlight | markup-only renderer path | | @peaceroad/markdown-it-renderer-fence/custom-highlight | Custom Highlight API renderer + payload/runtime helpers | | @peaceroad/markdown-it-renderer-fence/custom-highlight-runtime | browser runtime only (applyCustomHighlights, observeCustomHighlights, clearCustomHighlights) | | @peaceroad/markdown-it-renderer-fence/theme/rf-basic | color preset Shiki theme object and API provider helpers | | @peaceroad/markdown-it-renderer-fence/theme/rf-basic.css | complete color preset CSS | | @peaceroad/markdown-it-renderer-fence/theme/rf-monochrome | one-color Shiki markup theme object | | @peaceroad/markdown-it-renderer-fence/theme/rf-monochrome.css | complete one-color markup preset CSS |

Use @peaceroad/markdown-it-renderer-fence/theme/rf-basic for JavaScript helpers. CSS assets are exposed as CSS subpaths.

Split preset CSS is also available:

  • theme/rf-basic/base.css
  • theme/rf-basic/api/highlightjs.css
  • theme/rf-basic/api/shiki.css
  • theme/rf-basic/markup/shiki.css
  • theme/rf-basic/markup/highlightjs.css
  • theme/rf-monochrome.css
  • theme/rf-monochrome/markup/highlightjs.css
  • theme/rf-monochrome/markup/shiki.css

The plugin does not auto-load CSS or browser runtime JavaScript.

Features

  • markup mode with highlighter-owned HTML (md.options.highlight)
  • <samp> rendering for samp, shell, and console fence languages
  • per-fence {samp} / {code} tag overrides
  • line numbers via start / line-number-start
  • advanced line-number controls via line-number-skip / line-number-set
  • emphasized lines via em-lines / emphasize-lines
  • optional long-line spacer via lineEndSpanThreshold
  • optional pre-wrap via {wrap} / {pre-wrap}
  • comment markers via comment-mark
  • sidecar line notes via an immediate line-notes fence (notes alias)
  • advanced Custom Highlight API mode for span-free code text plus browser-applied ranges
  • optional first-party theme CSS and Shiki/provider helper exports

Fence Attribute Examples

```js {start="1" em-lines="2"}
const a = 1
console.log(a)
```
```bash {samp comment-mark="#"}
# setup
export NODE_ENV=test
```
```shell {code}
# render as <code> even though shell is normally sampLang
```
```js {start="5"}
const a = 1
console.log(a)
```
```line-notes
1: setup {width="7em"}
2: result {width="10em"}
```

For emitted HTML contracts and visual samples, see the files listed in Docs and Examples.

Main Options

Markup / shared options

| Option | Summary | | --- | --- | | attrsOrder | output attribute order; supports data-* wildcard | | setHighlight | call md.options.highlight when available | | setLineNumber | enable line wrapping when start / line-number-start is valid | | setEmphasizeLines | enable em-lines / emphasize-lines | | lineEndSpanThreshold | append line-end spacer spans for visually long lines | | setLineEndSpan | alias of lineEndSpanThreshold | | lineEndSpanClass | CSS class for line-end spacer spans | | setPreWrapStyle | inject inline pre-wrap style for wrap-enabled blocks | | sampLang | comma-separated languages rendered as <samp>; default: shell,console | | {samp} / {code} | per-fence tag override attrs | | langPrefix | language class prefix; defaults to md.options.langPrefix || 'language-' | | useHighlightPre | preserve highlighter-owned <pre><code> wrappers; disables line-splitting features | | onFenceDecision | debug hook for per-fence branch decisions | | onFenceDecisionTiming | include timing fields in onFenceDecision payloads |

Line features fail closed when highlighter output line counts do not match source line counts. In useHighlightPre passthrough, line-splitting features and <samp> conversion are intentionally skipped.

Custom Highlight API options

| Option | Summary | | --- | --- | | highlightRenderer | dispatcher mode: markup, api, or custom-highlight-api | | customHighlight.provider | shiki, hljs, or custom | | customHighlight.highlighter | Shiki highlighter with synchronous codeToTokens | | customHighlight.hljsHighlight | highlight.js-style function for the hljs provider | | customHighlight.getRanges | synchronous custom range provider | | customHighlight.theme | Shiki theme name or { light, dark, default? } | | customHighlight.shikiScopeMode | auto, color, semantic, or role | | customHighlight.includeScopeStyles | include payload scopeStyles when available | | customHighlight.transport | env or inline-script | | customHighlight.fallback | provider-error fallback: plain or markup | | customHighlight.lineFeatureStrategy | hybrid or disable |

For detailed API-mode styling, runtime, role-mode, and payload guidance, see Custom Highlight Styling Guide and Code Highlighting Design.

Custom Highlight API Mode

API mode renders escaped code text and emits payload ranges. It does not activate browser highlights by itself; call the runtime in the browser.

import MarkdownIt from 'markdown-it'
import markdownItAttrs from 'markdown-it-attrs'
import { createHighlighter } from 'shiki'
import rendererFenceApi, {
  applyCustomHighlights,
  renderCustomHighlightPayloadScript,
} from '@peaceroad/markdown-it-renderer-fence/custom-highlight'
import {
  createRfBasicShikiCustomHighlightOptions,
  rfBasicShikiTheme,
  rfBasicThemeName,
} from '@peaceroad/markdown-it-renderer-fence/theme/rf-basic'

const highlighter = await createHighlighter({
  themes: [rfBasicShikiTheme],
  langs: ['javascript', 'typescript', 'json'],
})

const md = MarkdownIt({ html: true })
  .use(markdownItAttrs)
  .use(rendererFenceApi, {
    customHighlight: createRfBasicShikiCustomHighlightOptions({
      highlighter,
      theme: rfBasicThemeName,
      shikiScopeMode: 'role',
      includeScopeStyles: false,
      transport: 'env',
    }),
  })

const env = {}
const html = md.render('```js
const x = 1
```', env)
const payloadScript = renderCustomHighlightPayloadScript(env)

// Browser side:
applyCustomHighlights(document)

For lazy apply and color-scheme watching:

import { observeCustomHighlights } from '@peaceroad/markdown-it-renderer-fence/custom-highlight-runtime'

observeCustomHighlights(document, {
  applyOptions: { colorScheme: 'auto', incremental: true },
  watchColorScheme: true,
})

Use markup mode instead when the target page cannot run runtime JavaScript.

Theme

The optional preset theme is a package artifact, not an automatically loaded dependency.

@import "@peaceroad/markdown-it-renderer-fence/theme/rf-basic.css";

The color preset covers base code blocks, samp, line features, highlight.js markup classes, Shiki API scopes, and highlight.js API scopes.

For one-color print/monochrome output, use markup mode and import the opt-in monochrome override:

@import "@peaceroad/markdown-it-renderer-fence/theme/rf-monochrome.css";

For theme design details, see theme/rf-basic/README.md and theme/rf-monochrome/README.md.

Helper Exports

From @peaceroad/markdown-it-renderer-fence/custom-highlight:

  • applyCustomHighlights
  • observeCustomHighlights
  • clearCustomHighlights
  • shouldRuntimeFallback
  • getCustomHighlightPayloadMap
  • renderCustomHighlightPayloadScript
  • renderCustomHighlightScopeStyleTag
  • customHighlightPayloadSchemaVersion
  • customHighlightPayloadSupportedVersions

From @peaceroad/markdown-it-renderer-fence/theme/rf-basic:

  • rfBasicShikiTheme
  • rfBasicThemeName
  • createRfBasicShikiTheme
  • createRfBasicShikiCustomHighlightOptions
  • createRfBasicHighlightjsCustomHighlightOptions
  • rfBasicSyntaxCssVars
  • createRfBasicShikiRoleScopeColorVars

From @peaceroad/markdown-it-renderer-fence/theme/rf-monochrome:

  • rfMonochromeShikiTheme
  • rfMonochromeShikiThemeName
  • rfMonochromeThemeName
  • createRfMonochromeShikiTheme

Docs and Examples

Examples are demonstration and verification assets. Do not import runtime or theme helpers from example/; use the public package entry points above.

Tests and Benchmarks

npm test
npm run test:provider:contract
npm run test:provider:role
npm run test:provider:role:holdout
npm run test:provider:matrix
npm run test:performance
npm run test:performance:runtime

License

MIT (LICENSE)