Markdown extensions catalog
The catalog of non-CommonMark Markdown features wired into Pennington's Markdig pipeline. Markdig's own built-in syntax (tables, footnotes, and so on) is not covered here.
| Extension | Syntax | Controlled by | Doc page |
|---|---|---|---|
| Tabs | Adjacent fences with tabs=true |
UseTabbedCodeBlocks |
Tabbed code |
| Alerts | > [!KIND] inside blockquote |
UseCustomAlerts |
Alerts |
| Code annotations | Trailing-comment [!code …] directive |
UseSyntaxHighlighting |
Code annotations |
| Cross-reference tags | <xref:uid> or href="xref:uid" |
XrefHtmlRewriter (response stage) |
Cross-references |
Tabs
The tabs extension collapses a run of consecutive fenced code blocks — starting with one that carries tabs=true — into a single tabbed container rendered as role="tablist" / role="tab" / panel regions, with the first tab active by default.
Syntax
```csharp tabs=true title="C#"
// block A
```
```razor title="Razor"
@* block B *@
```
Each fenced block in the consecutive run becomes a tab panel; only the first block requires tabs=true to open the group.
Arguments
tabstrueDefault:(absent)Applies to the first fence in the group. Marks a fenced block as the start of a tabbed run; consecutive subsequent fences join the same group.
titlestring (optionally quoted)Default:pretty language name derived from the info stringApplies to each fence in the group. Overrides the label shown on the tab button.
Arguments are key=value pairs; quoted values are allowed. See Code-block argument reference for the full grammar.
Emitted CSS classes
| Option | Default class | Role |
|---|---|---|
OuterWrapperCss |
not-prose |
Outer <div> wrapper that opts out of prose styling. |
ContainerCss |
tab-container |
Container wrapping tablist and panels. |
TabListCss |
tab-list |
role="tablist" row. |
TabButtonCss |
tab-button |
role="tab" <button> (carries data-state="active"|"inactive"). |
TabPanelCss |
tab-panel |
aria-labelledby-bound panel wrapping the rendered code block. |
Classes are configurable via TabbedCodeBlockRenderOptions passed to UseTabbedCodeBlocks.
Minimal example
Markdown source showing a two-fence tabbed group from the DocSite authoring example:
---
title: Authoring a doc page
description: Populate DocSiteFrontMatter, add an alert, and group code samples into tabs.
tags:
- authoring
- front-matter
- markdown
sectionLabel: Guides
order: 20
---
# Authoring a doc page
## Callouts
> [!NOTE]
> Alerts render with a coloured left border and an icon matching the kind.
## Tabbed code groups
```bash tabs=true title="dotnet CLI"
dotnet add package Pennington
```
```powershell tabs=true title="PowerShell"
Install-Package Pennington
```
```xml tabs=true title="csproj"
<PackageReference Include="Pennington" Version="*" />
```
Alerts
The alerts extension parses a GitHub-flavored > [!KIND] token as the first line of a blockquote and replaces the QuoteBlock with an AlertBlock carrying two CSS classes. Pennington registers its own CustomAlertInlineParser ahead of Markdig's built-in alert parser; the blockquote form is the only accepted syntax.
Syntax
> [!NOTE]
> Body text of the alert, CommonMark rendered.
KIND is a case-insensitive alphabetic token; unrecognized kinds still parse and emit a markdown-alert-<kind> class using the lowercased token.
Arguments
Alerts take no arguments; the kind token is the only variable and is drawn from the set listed under built-in kinds.
Built-in kinds and emitted CSS classes
Every alert receives two classes: markdown-alert (constant) and markdown-alert-<kind> (derived from the lowercased token). The five built-in GitHub-compatible kinds and their emitted secondary classes are listed below.
| Kind token | Secondary class | Typical use |
|---|---|---|
NOTE |
markdown-alert-note |
Supplementary information. |
TIP |
markdown-alert-tip |
Helpful aside. |
CAUTION |
markdown-alert-caution |
Risky operation — consequences before action. |
WARNING |
markdown-alert-warning |
Something likely to go wrong. |
IMPORTANT |
markdown-alert-important |
Must-read information. |
Minimal example
Markdown excerpt from the DocSite authoring example showing a [!NOTE] block in context:
---
title: Authoring a doc page
description: Populate DocSiteFrontMatter, add an alert, and group code samples into tabs.
tags:
- authoring
- front-matter
- markdown
sectionLabel: Guides
order: 20
---
# Authoring a doc page
## Callouts
> [!NOTE]
> Alerts render with a coloured left border and an icon matching the kind.
> Supported kinds include `NOTE`, `TIP`, `IMPORTANT`, `WARNING`, and
> `CAUTION`.
Code annotations
After syntax highlighting, each rendered line is scanned for a [!code …] directive inside a language-appropriate comment. The comment is stripped and a CSS class is applied to the line and optionally to the enclosing <pre>. The word: variant wraps a matching substring in a span rather than acting on the whole line; the include-start / include-end / exclude-start / exclude-end directives remove surrounding lines from the output.
Syntax
```csharp
var x = 1; // [!code highlight]
var y = 2; // [!code ++]
var z = 3; // [!code word:z|renamed from q]
```
The directive must appear inside a recognized comment marker for the language (//, #, --, <!-- -->, *, %, ', REM, ;, /* */). The directive and any now-empty comment wrapper are removed, leaving trailing content intact.
Notations
highlightLine class
highlight,<pre>classhas-highlighted. Marks a line as emphasized. Alias:hl.++Line class
diff-add,<pre>classhas-diff. Marks a line as an addition.--Line class
diff-remove,<pre>classhas-diff. Marks a line as a removal.focusLine class
focused,<pre>classhas-focused. Focuses listed lines; all others receiveblurred.errorLine class
error,<pre>classhas-errors. Marks a line as an error.warningLine class
warning,<pre>classhas-warnings. Marks a line as a warning.word:TEXT<pre>classhas-word-highlights. Wraps the first occurrence ofTEXTin a<span class="word-highlight">. ReplaceTEXTwith the substring to highlight (the literal directive usesword:followed by the text, with no angle brackets or quoting — for example[!code word:Multiply]).word:TEXT|MESSAGE<pre>classhas-word-highlights. As above, but wraps the match inword-highlight-with-messageand renders an adjacentword-highlight-messagecallout containingMESSAGE. Use a literal|to separate the matched text from the message — for example[!code word:queue|renamed from buffer].include-start / include-endStructural. Keep only lines between the matching start/end markers; markers are removed.
exclude-start / exclude-endStructural. Drop lines between the matching start/end markers; markers are removed.
Emitted CSS classes
Line-level classes (highlight, diff-add, diff-remove, focused / blurred, error, warning) are added to the <span class="line"> wrapper. Block-level classes (has-highlighted, has-diff, has-focused, has-errors, has-warnings, has-word-highlights) are added to the outer <pre>. The word: notation emits word-highlight or word-highlight-with-message on the wrapped span, plus the callout elements word-highlight-wrapper, word-highlight-message, word-highlight-arrow-container, word-highlight-arrow-outer, and word-highlight-arrow-inner.
Minimal example
An annotated fence exercising [!code highlight], [!code ++], and [!code --]; the enclosing <pre> receives has-highlighted and has-diff, and the trailing directive comments are stripped from the emitted HTML:
```csharp
var message = "hello"; // [!code highlight]
var added = "added"; // [!code ++]
var removed = "gone"; // [!code --]
```
Cross-reference tags
xref: links authored in markdown are resolved after rendering against the uid-to-route map built from every page's front-matter uid:. Two surface forms are supported: the tag form <xref:uid> is handled in a pre-parse string pass (it is not valid HTML), and the attribute form [text](xref:uid) has its rendered href="xref:uid" rewritten during the DOM pass. Unknown uids emit a diagnostic that surfaces in the dev overlay and in the static-build report.
Syntax
See <xref:reference.api.pennington-options>.
See [PenningtonOptions](xref:reference.api.pennington-options).
uid is the exact string declared in a page's front-matter uid: key.
Arguments
The only variable is the uid token. The tag form derives its link text from the target page's title; the attribute form uses the supplied link text verbatim.
Emitted CSS classes
The rewriter emits a standard <a href="…"> element with no added class; styling is delegated to the surrounding prose stylesheet.
Minimal example
Both surface forms resolving the same uid — the tag form derives its link text from the target page title, the attribute form uses the supplied label verbatim:
See <xref:reference.api.pennington-options> for the full options catalog.
Configure MonorailCSS through [the options record](xref:reference.api.monorail-css-options).
See also
- How-to: Tabbed code
- How-to: Alerts
- How-to: Code annotations
- How-to: Cross-references
- Related reference: Code-block argument reference