---
title: Markdown extensions catalog
description: "Every non-CommonMark Markdown feature Pennington adds — tabs, alerts, code annotations, and cross-reference tags — with syntax, arguments, and emitted classes."
canonical_url: https://usepennington.net/reference/markdown/extensions/
sidecar_url: https://usepennington.net/reference/markdown/extensions.md
content_hash: sha256:05d97ff5e152d48b8112732c63c53aecc31a537e5b99a07d77c11d69d5d0b7f1
tokens: 3715
uid: reference.markdown.extensions
reading_time_minutes: 10
---

Reference
# Markdown extensions catalog

Every non-CommonMark Markdown feature Pennington adds — tabs, alerts, code annotations, and cross-reference tags — with syntax, arguments, and emitted classes.

 
The catalog of non-CommonMark Markdown features enabled in 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     Tabbed code Adjacent fences with `tabs=true` `UseTabbedCodeBlocks` [Tabbed code](https://usepennington.net/how-to/code-samples/tabbed-code.md)   Content tabs `# [Label](#tab/id)` headings ended by `---` `UseContentTabs` [Content tabs](https://usepennington.net/how-to/rich-content/content-tabs.md)   Includes `[!INCLUDE …]` (full form under Includes) Markdown parser (always on) [Reuse shared content](https://usepennington.net/how-to/pages/include-shared-content.md)   Alerts `> [!KIND]` inside blockquote `UseCustomAlerts` [Alerts](https://usepennington.net/how-to/rich-content/alerts.md)   Code annotations Trailing-comment `[!code …]` directive `UseSyntaxHighlighting` [Code annotations](https://usepennington.net/how-to/code-samples/code-annotations.md)   Cross-reference tags `<xref:uid>` or `href="xref:uid"` Resolved in the response stage [Cross-references](https://usepennington.net/how-to/navigation/linking.md)   Shortcodes `<?# Name args /?>` Registered `IShortcode` handlers (pre-parse expansion) [Shortcodes](https://usepennington.net/how-to/markdown-pipeline/shortcodes.md)    
## Tabs

 
Renders a run of consecutive fenced code blocks (starting with one that carries `tabs=true`) as a single tabbed container with `role="tablist"`, `role="tab"`, and panel regions. The first tab is active by default.

 
### Syntax

 
````markdown
```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

 
    Name Type Default Description     `tabs` `true` (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.   `title` `string` (optionally quoted) pretty language name derived from the info string Applies 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](https://usepennington.net/reference/markdown/code-block-args.md) 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:

 
````markdown:symbol
---
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 title="PowerShell"
Install-Package Pennington
```
  
```xml title="csproj"
<PackageReference Include="Pennington" Version="*" />
```
````

 
## Content tabs

 
Groups a run of DocFX-style tab headings into a single tabset whose panels hold arbitrary Markdown — prose, lists, code, callouts. Distinct from tabbed code: the tab strip sits in the reading flow rather than inside code chrome.

 
### Syntax

 
A tab opens with a level-1 heading whose only inline is a link to `#tab/<id>`; the link text is the button label. Consecutive tab headings form one group, ended by a thematic break (`---`).

 
```markdown
# [Bash](#tab/bash)

Use the bash variant.

# [PowerShell](#tab/pwsh)

Use the PowerShell variant.

---
```

 
### Dependent tabs

 
A third path segment — `#tab/<id>/<condition>` — gates the tab on another group's selection. `<condition>` is a tab id that has its own plain group elsewhere on the page; the dependent panel shows only when its `<id>` is the active button and its `<condition>` is that other group's selected id.

 
```markdown
# [.NET](#tab/lang/linux)

.NET on Linux.

# [.NET](#tab/lang/windows)

.NET on Windows.

---
```

 
### Arguments

 
    Name Type Default Description     `id` identifier — First segment after `#tab/`. Identifies the tab; ids are page-wide, so equal ids select together.   `condition` identifier (absent) Optional second segment. Gates the tab on the selected id of the condition's own group.    
### Emitted CSS classes

 
    Element Class Attributes Role     Container `ctabs` `data-content-tabs` Tabset wrapper; not `not-prose`.   Tab strip `ctabs-bar not-prose` `role="tablist"` Button row; `not-prose` isolates the buttons from page typography.   Button `ctab-btn` `data-tab`, `data-active`, `role="tab"`, `aria-selected` One per distinct id.   Panel `ctab-panel` `data-tab`, `data-condition`, `data-active`, `role="tabpanel"` One per tab heading; not `not-prose`, so content keeps prose styling.    
 
The first panel is active in the server-rendered HTML; the client script recomputes selection on load, syncs equal ids page-wide, and persists each choice in `localStorage`.

 
### Minimal example

 
A two-tab group whose panels hold prose; the `---` thematic break closes the set:

 
```markdown
# [Bash](#tab/bash)

Run the bash script.

# [PowerShell](#tab/pwsh)

Run the PowerShell script.

---
```

 
## Includes

 
Splices a referenced Markdown file into the host page during parsing. The directive works as a standalone block or inline within a sentence; the referenced file is expanded recursively.

 
### Syntax

 
```markdown
[!INCLUDE [block partial](../_includes/partial.md)]

Text before [!INCLUDE [inline partial](../_includes/snippet.md)] and after.
```

 
### Arguments

 
    Name Type Default Description     `title` string — Bracketed label. Parsed but not emitted; present for DocFX compatibility.   `path` path — File path resolved relative to the referencing file. Absolute URLs are not fetched.    
### Behavior

 
    Case Result     Target file found Content is spliced in; a leading YAML front-matter block is stripped first.   Directive in a fenced code block Left verbatim, so the syntax can be documented.   Target missing Replaced with `<!-- Pennington: include not found: <path> -->`.   Include cycle, or depth past 16 Replaced with `<!-- Pennington: include cycle broken: <path> -->`.   Absolute URL path Replaced with `<!-- Pennington: include skipped (not a local file): <path> -->`.    
 
Relative links and images inside an included file are not rebased — they resolve as if written in the host page.

 
### Minimal example

 
A standalone block include splicing a shared partial into the host page:

 
```markdown
[!INCLUDE [install steps](../_includes/install.md)]
```

 
## Alerts

 
Parses a GitHub-flavored `> [!KIND]` token as the first line of a blockquote and emits an `AlertBlock` with two CSS classes. The blockquote form is the only accepted syntax.

 
### Syntax

 
```markdown
> [!NOTE]
> Body text of the alert, CommonMark rendered.
```

 
`KIND` is a case-insensitive alphabetic token.

 
### Arguments

 
    Name Type Default Description     `KIND` identifier — One of `NOTE`, `TIP`, `CAUTION`, `WARNING`, `IMPORTANT`. Case-insensitive. Unrecognized tokens still parse, emitting `markdown-alert-<kind>` using the lowercased value.    
### Built-in kinds and emitted CSS classes

 
Every alert receives two classes: `markdown-alert` (constant) and `markdown-alert-<kind>`.

 
    Kind Secondary class Typical use     `NOTE` `markdown-alert-note` Supplementary information.   `TIP` `markdown-alert-tip` Helpful aside.   `CAUTION` `markdown-alert-caution` Risky operation.   `WARNING` `markdown-alert-warning` Something likely to go wrong.   `IMPORTANT` `markdown-alert-important` Must-read information.    
### Minimal example

 
Markdown excerpt showing a `[!NOTE]` block in context:

 
```markdown:symbol
---
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 directive is stripped and a CSS class is applied to the line (and optionally to the enclosing `<pre>`). The `word:` variant wraps a matching substring; the `include-start`/`include-end`/`exclude-start`/`exclude-end` directives remove surrounding lines from the output.

 
### Syntax

 
````markdown
```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 comment marker recognized for the language; the marker and any now-empty comment wrapper are removed, leaving trailing content intact. [Code-block argument reference](https://usepennington.net/reference/markdown/code-block-args.md) is the canonical reference for the full directive set (`highlight`, `++`/`--`, `focus`, `error`, `warning`, `word:`, the `include`/`exclude` region markers) and the recognized comment markers.

 
### 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:

 
````markdown
```csharp
var message = "hello";   // [!code highlight]
var added = "added";     // [!code ++]
var removed = "gone";    // [!code --]
```
````

 
## Cross-reference tags

 
`xref:` links resolve 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>` and the attribute form `[text](xref:uid)`. Unknown uids emit a diagnostic that surfaces in the dev overlay and in the static-build report.

 
### Syntax

 
```markdown
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

 
    Name Type Default Description     `uid` identifier — Exact string declared in a page's front-matter `uid:` key. The tag form derives 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:

 
```markdown
See <xref:reference.api.pennington-options> for the full options catalog.

Configure MonorailCSS through [the options record](xref:reference.api.monorail-css-options).
```

 
## Shortcodes

 
Shortcodes run before Markdig parses the page rather than as a Markdig extension: each `<?# Name args /?>` directive is expanded to text or HTML first by a registered `IShortcode` handler, and the result flows through the pipeline as ordinary markdown. Names are case-insensitive.

 
### Syntax

 
A call has a self-closing form and a block form with inline content:

 
```markdown
<?# Name positional key="value" /?>

<?# Name ?>inline content<?#/ Name ?>
```

 
To document a directive without expanding it, prefix the opener with a backslash — the expander emits the directive verbatim. (Every literal directive on this page uses that escape.)

 
### Built-ins

 
    Name Arguments Description     `Version` `format=full\|major\|minor\|informational` (default `full`) Emits the host application's assembly version.   `PackageVersion` none Emits Pennington's own published NuGet version.    
 
Unknown names and handler failures degrade to an HTML comment plus a warning diagnostic, so one bad call site never fails the render. See [the shortcodes how-to](https://usepennington.net/how-to/markdown-pipeline/shortcodes.md) for the handler contract and registration.

 
## See also

 
 - How-to: [Add a Markdig extension or inline parser](https://usepennington.net/how-to/markdown-pipeline/markdig-extension.md) — register syntax this catalog doesn't list
 - How-to: [Tabbed code](https://usepennington.net/how-to/code-samples/tabbed-code.md)
 - How-to: [Content tabs](https://usepennington.net/how-to/rich-content/content-tabs.md)
 - How-to: [Reuse shared content](https://usepennington.net/how-to/pages/include-shared-content.md)
 - How-to: [Alerts](https://usepennington.net/how-to/rich-content/alerts.md)
 - How-to: [Code annotations](https://usepennington.net/how-to/code-samples/code-annotations.md)
 - How-to: [Cross-references](https://usepennington.net/how-to/navigation/linking.md)
 - How-to: [Expand a directive before Markdig parses](https://usepennington.net/how-to/markdown-pipeline/shortcodes.md)
 - Related reference: [Code-block argument reference](https://usepennington.net/reference/markdown/code-block-args.md)
 
 
[Previous
                
                Folder sidecar (`_meta.yml`)](https://usepennington.net/reference/front-matter/folder-sidecar.md)[Next
                    
                Code-block argument reference](https://usepennington.net/reference/markdown/code-block-args.md)