---
name: markdown-plus-plus
description: >
  AUTHORITATIVE REFERENCE for Markdown++ syntax. Use when reading or writing
  .md files that contain any of these signals (whitespace inside the HTML
  comment is irrelevant): <!--style:--> directives, <!--multiline--> table
  directives, <!--condition:--> blocks, <!--include:--> directives,
  <!--marker:--> or <!--markers:-->, <!--#alias--> anchors, $variable; tokens,
  or mdpp-version: in YAML frontmatter. Also use when creating a .md file
  modeled after another file containing any of these signals. Use for editing,
  validating, migrating, or auditing Markdown++ source documents.
---

<objective>

# markdown-plus-plus

Read and write Markdown++ documents - an extended Markdown format with variables, conditions, custom styles, file includes, and markers.

**Do not use training data for Markdown++.** This is an extended documentation format built on CommonMark. Markdown++ is fully backward compatible with CommonMark -- all extensions use HTML comment tags and are ignored by standard Markdown parsers. Use only this skill's references for extension syntax and behavior rules.
</objective>

<overview>

## Overview

Markdown++ extends CommonMark with HTML comment-based extensions. All extensions (except variables) use HTML comments for backward compatibility with standard Markdown renderers.

### Quick Reference

- **Version Declaration**: `mdpp-version: 1.0` -- Spec version in YAML frontmatter
- **Variables**: `$variable_name;` -- Inline, reusable content
- **Styles**: `<!--style:Name-->` -- Block (above) or Inline (before)
- **Aliases**: `<!--#alias-name-->` -- Anchor for `[text](#alias-name)` links
- **Conditions**: `<!--condition:name-->...<!--/condition-->` -- Show/hide content by format
- **Includes**: `<!--include:path/to/file.md-->` -- Insert file contents
- **Markers**: `<!--markers:{"Key": "val"}-->` -- Metadata for search/processing
- **Multiline Tables**: `<!-- multiline -->` -- Enable block content in cells

</overview>

<command_block_syntax>

## Command Block Syntax (MUST follow exactly)

ALWAYS use this format -- no variations. Content MUST follow the directive on the very next line with no blank line between them.

### Style + alias (combined)

```markdown
<!-- style:StyleName ; #anchor-name -->
Content immediately follows (NO blank line).
```

### Markers + alias (combined)

```markdown
<!-- markers:{"Keywords": "word1, word2", "Description": "Brief description"} ; #anchor-name -->
## Heading immediately follows (NO blank line).
```

### Single-directive forms

```markdown
<!-- style:StyleName -->
Content immediately follows.
```

```markdown
<!-- marker:Keywords="..." -->
Content immediately follows.
```

```markdown
<!-- #anchor-name -->
Content immediately follows.
```

### NEVER

- Put a blank line between a directive comment and its target content. The blank line silently breaks the [attachment rule](../../../../GLOSSARY.md#attachment-rule); the directive passes through as a regular HTML comment with no effect.
- Place the alias on a separate line from `style:` or `markers:`. Stacked HTML comments leave the top one orphaned -- combine them with `;` in a single directive instead.
- Vary the spacing inside `<!-- ... -->` or around `;` arbitrarily. The canonical form has a space after `<!--`, a space before `-->`, and spaces around each `;`. The no-space form (`<!--style:A;#b-->`) is also valid; the spaced form is recommended for readability per `references/syntax-reference.md` (Combined Commands -> Whitespace).

See `references/syntax-reference.md` (Attachment Rules, Combined Commands) and the `<common_mistakes>` section below for the full rule set and edge cases. See `../../../../spec/attachment-rule.md` for the normative definition.

</command_block_syntax>

<syntax_examples>

## Syntax Examples

### Variables

Variables store reusable values across documents. They use `$name;` syntax (dollar sign, name, semicolon).

```markdown
Welcome to $product_name;, version $version;.
The **$product_name;** application supports...
```

**Rules:**
- Names must follow [Naming Rules](references/syntax-reference.md#naming-rules) (letter or underscore first)
- Must end with semicolon
- No spaces in variable names
- Case-sensitive: `$Product;` differs from `$product;`
- Escape with `\$` to prevent variable interpretation, or use inline code (`` `$name;` ``)

**Valid:** `$product_name;`, `$version-2;`, `$my_var;`
**Invalid:** `$product name;` (space), `$product` (no semicolon)

**Variable values:** Values can contain Markdown syntax (`**bold**`, `[link](url)`) — it renders normally. Values cannot contain condition or include directives — those are resolved before variable substitution. See `spec/processing-model.md` for processing order.

### Custom Styles

Styles override default formatting. Placement depends on element type.

**Block-level** (place on line directly above element, no blank line):
```markdown
<!--style:CustomHeading-->
# My Heading

<!--style:NoteBlock-->
> This is a styled blockquote.
```

**IMPORTANT:** Block commands must be attached to the element (no blank line between). A blank line breaks the association and passes through as a regular Markdown comment with no Markdown++ association/effect.

**Inline** (place immediately before the element, no space):
```markdown
This is <!--style:Emphasis-->**important text**.
```

See `references/syntax-reference.md` for nested list indentation rules and table styling.

### Custom Aliases

Aliases create stable internal link anchors. **Aliases are block-level only** -- they must appear on their own line above a block element, not inline.

```markdown
<!--#getting-started-->
## Getting Started

See [Getting Started](#getting-started) for an introduction.
```

**Cross-document links:** `[API Reference](api.md#authentication)`

**Rules:**
- Block-level only -- must be on its own line above a block element (inline aliases are not supported)
- Names must follow [Naming Rules](references/syntax-reference.md#naming-rules) (digit-first allowed for aliases)
- No spaces (alias ends at first space)
- Must start with `#` inside the comment
- Keep alias values unique within each file
- Must be attached to an element (no blank line between alias and element) -- same rule as styles

**Auto-generated alias collisions:** When multiple headings produce the same auto-generated alias, the first heading keeps the bare alias and subsequent headings receive `-2`, `-3`, etc. (e.g., `setup`, `setup-2`, `setup-3`). Custom aliases and auto-generated aliases occupy separate namespaces -- when a custom alias and an auto-generated alias share the same identifier, both exist independently, but the custom alias wins at link resolution time (no suffixing or displacement of the auto-generated alias). Both overlap types are resolved silently -- no diagnostic is emitted. Custom alias duplicates remain an error (MDPP008). When a heading with a suffixed auto-generated alias also has a custom alias, both are valid anchors (e.g., `#db-setup` and `#setup-2`). See `spec/element-interactions.md` for the full algorithm.

**Recommended pattern for referenceable headings:** When authoring or editing a Markdown++ topic file, apply the **alias+slug+linkref** triple (see [GLOSSARY.md](../../../../GLOSSARY.md#triple)) on every heading meant to be externally referenceable:

```markdown
<!-- style:Heading2; #200020 -->
## Installation

[installation]: #200020 "Installation"
```

- **When the rule fires:** the file's title (H1), and H2 headings that name a major section a reader is likely to deep-link to.
- **What to author:** all three pieces, adjacent in source -- the `<!-- style:HeadingN; #target -->` directive on the line directly above the heading, the heading itself, and a `[semantic-slug]: #target "Title"` link reference definition on the line directly after the heading (separated by a single blank line). Do not migrate the link reference definition to a block at the bottom of the file. Just an alias (without the paired definition) makes the heading internally addressable but does not establish a semantic cross-reference. The slug may be a separate semantic name (as in the example above) or the alias value itself when the alias is already semantic and unique. See the *Choosing the slug* guidance in [`references/best-practices.md` § Semantic Cross-References on Topic-Defining Headings](references/best-practices.md#choosing-the-slug).
- **When the rule does NOT fire:** H3+ headings are author judgement -- do not apply the triple reflexively to every subsection. A custom alias used purely as an internal anchor (no external references expected) is also valid on its own.

The triple gives cross-context resolution (standalone, single-file, assembly), section-move safety through co-location, and -- for automation pipelines that mint unique anchors -- a single identifier per heading via the slug = alias variant. See [Semantic Cross-References on Topic-Defining Headings](references/best-practices.md#semantic-cross-references-on-topic-defining-headings) for the full rationale and the inline-anchor-vs-triple comparison.

Use `scripts/add-aliases.py` to auto-generate aliases for headings. The script writes alias anchors only -- it does not author the paired link reference definitions, so you must add those by hand when the heading is meant to be externally referenceable.

### Conditions

Conditions show or hide content based on output format.

```markdown
<!--condition:web-->
Visit our [website](https://example.com) for updates.
<!--/condition-->
```

**Operators:** Space (AND), Comma (OR), Exclamation (NOT). Precedence: NOT > AND > OR.

```markdown
<!--condition:!draft,web production-->
Means: (!draft) OR (web AND production)
<!--/condition-->
```

**Inline:** `Contact us at <!--condition:web-->email<!--/condition--><!--condition:print-->the back cover<!--/condition-->.`

**Per-file scoping:** Condition blocks must open and close within the same file — they cannot span across an include boundary (MDPP012). See `spec/processing-model.md`.

**Condition state model:** Each condition name is either Visible or Hidden (assigned states); a name not defined in the condition set is Unset (see [GLOSSARY.md](../../../../GLOSSARY.md#unset)) — not an assigned state, but the absence of one. Unset conditions are not evaluated — the condition block passes through as-is (opening tag, content, and closing tag preserved), allowing the implementation to surface or resolve undefined conditional content downstream. In compound expressions (NOT/AND/OR), if any operand is Unset, the entire block passes through without evaluation.

**Variable substitution inside Unset blocks:** "Passes through as-is" refers to condition evaluation only. Variable substitution (Phase 1, Step 2) still resolves `$variable;` tokens inside Unset blocks because the content survives into that processing step. Include directives inside Unset blocks are NOT processed — the include tag passes through as literal text.

### File Includes

Insert content from other Markdown++ files.

```markdown
<!--include:shared/header.md-->
```

**Rules:** Paths relative to containing file. Recursive includes supported; circular includes detected and prevented. Must be alone on its line. Can be wrapped in conditions.

**Cross-file link resolution:** After include expansion, link reference definitions (`[slug]: url`) from all files share a single document-global scope. When multiple files define the same slug, first-definition-wins (per CommonMark 0.30) and include order determines priority. Cross-file duplicate slugs emit MDPP014 (warning). See `spec/cross-file-link-resolution.md` for full rules.

### Markers (Metadata)

Attach metadata to document elements for search, processing, or custom behavior.

**Single key-value:**
```markdown
<!--marker:Keywords="api, documentation"-->
```

**JSON format (multiple keys):**
```markdown
<!--markers:{"Keywords": "api, documentation", "Description": "API reference guide"}-->
```

**Index markers** create entries in generated indexes:
```markdown
<!--marker:IndexMarker="creating projects"-->
## Creating Projects
```

Format: `primary` for top-level, `primary:secondary` for nested, comma-separated for multiple entries. See `references/syntax-reference.md` for detailed marker examples.

### Multiline Tables

Enable block content (lists, blockquotes, styled elements) inside table cells.

```markdown
<!-- multiline -->
| Name | Details |
|------|---------|
| Bob  | Lives in Dallas. |
|      | - Enjoys cycling |
```

Every pipe-bearing row continues the current logical row. A row whose cells are all whitespace starts a new logical row — that's the only way to signal one. A no-pipe blank line ends the table. Cells on a continuation line appear empty when their column has no more content to flow there. Combine with style: `<!-- style:DataTable ; multiline -->`. See `references/syntax-reference.md` for multiline table rules.

**Extensions in cells:** Variables, block/inline styles, markers, conditions (wrapping complete rows only — not partial rows), and combined commands work inside multiline table cells. Includes and nested multiline tables are not supported in cells. See `spec/multiline-cell-extensions.md`.

### Combined Commands

Multiple commands in a single comment, separated by semicolons. Order: style, multiline, marker(s), #alias.

```markdown
<!-- style:CustomHeading ; marker:Keywords="intro" ; #introduction -->
# Introduction
```

### Inline Styling for Images and Links

```markdown
<!--style:CustomImage-->![Logo](images/logo.png "Company Logo")
[<!--style:CustomLink-->*Link text*](topics/file.md#anchor "Title")
```

### Content Islands (Blockquotes)

Blockquotes with custom styles create configurable content islands (see [GLOSSARY.md](../../../../GLOSSARY.md#content-island)) for callouts and notes.

```markdown
<!--style:BQ_Warning-->
> **Warning:** This is a styled warning block.
>
> Take note of the following:
> 1. First consideration
> 2. Second consideration
```

### Nested Lists with Styling

```markdown
<!--style:ProcedureList-->
1. First step
   - Sub-item A
   - Sub-item B
2. Second step
3. Third step
```

### Document Structure

**Topic map pattern** -- use includes to organize multi-chapter documents with conditional sections. See `references/examples.md` (Example 3) for a complete topic map example.

</syntax_examples>

<validation>

## Validation

Use the validation script to check Markdown++ syntax:

```bash
python scripts/validate-mdpp.py document.md
```

**Options:**
- `--verbose` - Show detailed output
- `--json` - Output errors as JSON
- `--strict` - Treat warnings as errors

**Common errors detected** (see [Error Code Reference](references/error-codes.md) for details):
- Unclosed condition blocks
- Invalid names — variables, styles, aliases, marker keys (see [Naming Rules](references/syntax-reference.md#naming-rules))
- Malformed marker JSON
- Circular file includes
- Duplicate alias values within a file
- Orphaned comment tags (tag not attached to element)
- Duplicate link reference slugs across included files (MDPP014)

## Alias Generation

Generate unique aliases for headings:

```bash
python scripts/add-aliases.py document.md --levels 1,2,3
```

**Options:**
- `--levels` - Comma-separated heading levels to process (e.g., `1,2,3`)
- `--dry-run` - Preview changes without modifying file
- `--prefix` - Add prefix to generated aliases

See `references/syntax-reference.md` for complete syntax rules.

</validation>

<common_mistakes>

## Common Mistakes

### 1. Blank Line Breaks Tag Attachment (The Attachment Rule)

**This is the #1 source of Markdown++ errors.** A blank line between a comment tag and its target element silently breaks the association. The tag passes through as a regular HTML comment with no visible error. This applies to styles, aliases, markers, and combined commands equally. Only conditions (which wrap content) and includes (standalone directives) are exempt.

**Wrong -- blank line breaks attachment:**
```markdown
<!-- style:NoteBox -->

> This blockquote will NOT receive the style.
```

**Right -- tag directly above target, no blank line:**
```markdown
<!-- style:NoteBox -->
> This blockquote receives the style.
```

**Wrong -- tag below content (tags attach downward only):**
```markdown
## Getting Started
<!-- #getting-started -->
```

**Right -- tag above content:**
```markdown
<!-- #getting-started -->
## Getting Started
```

**Wrong -- stacked tags (top tag is orphaned):**
```markdown
<!-- style:CustomHeading -->
<!-- #my-alias -->
## Heading
```

**Right -- combine with semicolons:**
```markdown
<!-- style:CustomHeading ; #my-alias -->
## Heading
```

See the [Attachment Rule specification](../../../../spec/attachment-rule.md) for the formal definition and all edge cases.

### 2. Mismatched Indentation on Nested Lists

**Indentation of Markdown++ comment tags must match the content line.** In nested lists, if the comment tag is indented but the following content is not (or vice versa), the style passes through as a regular Markdown comment and is not applied.

### 3. Missing Semicolon on Variables

**Variables without a trailing semicolon are not recognized.** `$product_name` is literal text; `$product_name;` is a variable reference. The semicolon is required.

</common_mistakes>

<references>

## Reference Files

- `references/syntax-reference.md` - Detailed syntax rules, edge cases, and validation codes
- `references/error-codes.md` - Error code reference with detection logic, trigger examples, and fixes
- `references/examples.md` - Real-world document examples
- `references/best-practices.md` - Usage guidance, naming conventions, and common mistakes
- `references/table-formatting.md` - Readable-table conventions and the `format-tables.py` rule set
- `references/comment-manipulation.md` - Rules for safely removing or simplifying Markdown++ directive comments during cleanup or migration
- `../../../../spec/specification.md` - Consolidated Markdown++ 1.0 specification
- `../../../../spec/processing-model.md` - Two-phase pipeline, variable/condition scoping, and processing order
- `../../../../spec/attachment-rule.md` - Formal tag-to-element binding rule, edge cases, and exempt tags
- `../../../../spec/element-interactions.md` - Style types, default names, compound naming, heading alias auto-generation and collision resolution
- `../../../../spec/formal-grammar.md` - Formal EBNF/PEG grammar for parser implementation
- `../../../../spec/cross-file-link-resolution.md` - Link reference scope and conflict rules across included files
- `../../../../spec/versioning.md` - Format version declaration syntax (`mdpp-version`) and compatibility rules
- `../../../../spec/multiline-cell-extensions.md` - Extension support and restrictions inside multiline table cells
- `../../../../spec/graceful-degradation.md` - Graceful degradation behavior in standard CommonMark renderers

</references>

<success_criteria>

## Success Criteria

- Markdown++ document uses correct syntax for all extensions
- Documents SHOULD declare `mdpp-version: 1.0` in YAML frontmatter (see [Format Versioning](../../../../spec/versioning.md))
- All named entities follow [Naming Rules](references/syntax-reference.md#naming-rules)
- Conditions have matching opening and closing tags
- File includes use valid relative paths
- Markers contain valid JSON (for `markers:` format)
- No circular includes detected
</success_criteria>
