Adding Superscript Support to Markdown
Mint renders Markdown through the markdown pipe (src/pipes/markdown.pipe.ts), which delegates to a single, shared markdown-it renderer held by MarkdownRendererService (src/services/markdown-renderer.service.ts). Because the renderer instance is created once in the service and reused everywhere, extending the supported syntax is done in one place.
This guide shows how to add superscript support β turning ^text^ into <sup>text</sup> β by installing the markdown-it-sup plugin.
The same steps apply to any markdown-it plugin (subscript, footnotes, task lists, β¦). Only the package name and the .use(...) call change.
Overviewβ
MarkdownRendererService owns the single markdown-it instance; the markdown pipe only calls render() on it. Adding a feature is a three-step process:
- Install the plugin package.
- Import it into
markdown-renderer.service.ts. - Register it on the renderer with
.use(...).
Once registered on the shared instance, every consumer of the markdown pipe (e.g. the Markdown preview conversion) automatically supports the new syntax β no change to markdown.pipe.ts is required.
Step 1 β Install the pluginβ
npm install markdown-it-sup
Step 2 β Register the plugin in MarkdownRendererServiceβ
Import the plugin and chain it onto the shared renderer with .use(...):
import { Injectable } from "@angular/core";
import MarkdownIt from "markdown-it";
// highlight-start
// markdown-it-sup ships no type definitions, so we suppress the missing-types error.
// @ts-expect-error - no type definitions provided by markdown-it-sup
import markdownItSup from "markdown-it-sup";
// highlight-end
/**
* Provides a single, shared markdown-it renderer instance for the whole application.
*/
@Injectable({ providedIn: "root" })
export class MarkdownRendererService {
// highlight-next-line
readonly renderer = new MarkdownIt({ html: true, linkify: true }).use(markdownItSup);
/** Renders a markdown string to an HTML string. */
render(value: string | null | undefined): string {
return value ? this.renderer.render(value) : "";
}
}
That is the only change required. The .use(markdownItSup) call registers the plugin's inline rule on the singleton renderer, so superscript becomes available to every consumer at once.
Because the renderer is owned by the service, markdown.pipe.ts does not need to be touched β it keeps delegating to MarkdownRendererService.render().
Step 3 β Usageβ
Wrap the text you want raised in a single caret (^) on each side:
| Markdown | Rendered HTML | Displayed as |
|---|---|---|
E = mc^2^ | E = mc<sup>2</sup> | E = mcΒ² |
1^st^ place | 1<sup>st</sup> place | 1Λ’α΅ place |
See note^1^ | See note<sup>1</sup> | See noteΒΉ |
In a template, nothing changes β the pipe is used exactly as before:
<div class="prose max-w-none dark:prose-invert" [innerHTML]="content | markdown"></div>
Before / afterβ
Given the Markdown source:
The area of the square is 5^2^ = 25 cm^2^.
Before installing the plugin, the carets are treated as literal text:
The area of the square is 5^2^ = 25 cm^2^.
After registering markdown-it-sup, the carets become superscript elements:
The area of the square is 5<sup>2</sup> = 25 cm<sup>2</sup>.
which renders visually as: The area of the square is 5Β² = 25 cmΒ².
Notes and limitationsβ
- No spaces inside the markers. The content between the carets cannot contain a raw space β
^a b^will not be rendered as superscript. Escape the space with a backslash if you need one:^a\ b^. - Missing TypeScript types.
markdown-it-supdoes not bundle type definitions and there is no@types/markdown-it-suppackage, so the// @ts-expect-errorcomment above is required for the build to pass. This mirrors the pattern already used elsewhere in the codebase for untyped packages. - Register once. Add the plugin only in
MarkdownRendererService. Registering it again on another renderer instance is unnecessary β the whole point of the service is a single shared instance. - Styling. The output is a plain
<sup>element, styled by the surroundingprose(Tailwind Typography) container. No extra CSS is needed. - Related plugins. Subscript (
~text~β<sub>text</sub>) is available via the companionmarkdown-it-subplugin and registered the same way:.use(markdownItSub). - Safe HTML. The
markdownpipe already returns trusted HTML viaDomSanitizer.bypassSecurityTrustHtml, so the generated<sup>tags are rendered rather than escaped. Only render Markdown from sources you trust.