remark-supersub

A Remark plugin adding pandoc-style superscript and subscript syntax to Markdown.

Library
npm
v1.0.0
18stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
22/100Needs Attention
Development Activity0
Maintenance0
Community16
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
45/100Fair
Architecture60
Code Quality55
Innovation30
Learning Curve35

remark-supersub is a lightweight plugin for the unified/remark ecosystem that teaches the Markdown parser to recognize pandoc-style superscript (^text^) and subscript (~text~) syntax, emitting dedicated superscript and subscript node types into the MDAST tree.

When paired with rehype, those nodes stringify directly to semantic <sup> and <sub> HTML elements, making it a drop-in addition to any remark-based Markdown-to-HTML pipeline that needs typographic superscripts and subscripts — ordinal suffixes, chemical formulas, footnote-style markers — without hand-writing raw HTML in source documents.

What You Get

  • Two new MDAST node types (superscript and subscript) inserted directly into the parse tree
  • Zero-config unified().use(supersub) integration alongside remark-parse and remark-rehype
  • Automatic HTML stringification to <sup>/<sub> tags when combined with rehype-stringify
  • Bundled TypeScript type definitions for the plugin’s transformer and node types

Common Use Cases

  • Rendering ordinal number suffixes like 21^st^ century in documentation sites
  • Writing chemical formulas such as H2O in technical or scientific Markdown content
  • Adding footnote-style superscript markers to blog posts or docs built on remark/rehype
  • Extending a static site generator’s Markdown pipeline with pandoc-compatible typography

Under The Hood

Architecture The plugin exports a single default factory, supersub(), that returns a Transformer matching the standard unified/remark plugin contract. Internally it runs two separate unist-util-visit passes over text nodes — one splitting on ^ to build superscript spans, another splitting on ~ for subscript spans — and replaces each matched text node in place via parent.children.splice. There is no internal layering, configuration surface, or shared state: the entire behavior lives in one small module, so the two visit passes are the only place correctness can drift, and any change to the split-and-splice logic directly changes output for every consumer.

Tech Stack Written in TypeScript and compiled with a plain tsc build step (no bundler), with a single runtime dependency, unist-util-visit. It targets the wider unified/remark/rehype ecosystem (developed against unified ^10, remark ^14, remark-parse ^10, remark-rehype ^9, and rehype-stringify ^9 in the monorepo’s dev dependencies) and ships compiled JS plus .d.ts files under lib/. The package lives inside a Lerna-managed monorepo alongside sibling remark plugins, each built and published independently.

Code Quality Tests exist via the ava test runner using snapshot assertions, but the fixture set covers only a single combined case (superscript and subscript together) with no dedicated coverage for edge cases like unmatched delimiters or escaped characters. The code favors TypeScript non-null assertions (parent!, i!) over explicit null handling, and an inline eslint-disable-next-line comment suggests looser type/lint discipline than the presence of TypeScript alone implies. The monorepo also carries two parallel, seemingly redundant test configurations (a Jest config plus the actual ava config used in CI), which is a minor consistency smell. CI runs on GitHub Actions across Node 14 and 15, executing the test suite on every push and pull request.

API Design The public surface is minimal by design: a single default export registered with one .use(supersub) call and no configuration options. Naming mirrors pandoc’s own ^text^/~text~ convention, so anyone familiar with pandoc superscript/subscript syntax needs no additional learning. Getting started requires only wiring it into an existing unified().use(remark-parse).use(supersub).use(remark-rehype).use(rehype-stringify) chain, which the README documents directly with a runnable example.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search