---
title: Formatting
---

Panache's formatting rules are designed to produce clean, consistent Markdown
output that adheres to common style guidelines while preserving the semantic
meaning of the original document.

## Text Wrapping

### Paragraphs

Panache supports three modes of text wrapping for paragraphs, which are
controlled via the [configuration](configuration.qmd) file:

```toml
[format]
wrap = "reflow" # or "preserve" or "sentence"
```

If `wrap` is set to `reflow`, panache will reformat paragraphs to fit within the
number of columns specified by the `line-width` configuration option (default
80). If `wrap` is set to `preserve`, panache will keep existing line breaks and
not reflow paragraphs. If `wrap` is set to `sentence`, panache will break lines
at sentence boundaries, ensuring that each sentence starts on a new line.

Input
:   ```markdown
    First sentence with a [link text](https://example.com) and inline math $a + b = c$. Second sentence; third sentence!
    ```

Output (`"reflow"`)
:   ```markdown
    First sentence with a [link text](https://example.com) and inline math
    $a + b = c$. Second sentence; third sentence!
    ```

Output (`"sentence"`)
:   ```markdown
    First sentence with a [link text](https://example.com) and inline math $a + b = c$.
    Second sentence; third sentence!
    ```

### Preserving Hard Breaks

Hard line breaks, which are created either by ending a line with two or more
spaces (\``) or by using a backslash (`\\n\`), are preserved regardless of the
wrapping mode:

Input (with `  ` hard break)
:   ```markdown
    First line  
    Second line
    ```

Output
:   ```markdown
    First line\
    Second line
    ```

## Headings

### ATX Headings

Headings are normalized with consistent spacing. Trailing `#` characters in ATX
headings are removed.

Input
:   ```markdown
    #Heading 1
    Text

    ##  Heading 2

    ###   Heading 3
    ```

Output

:   ```markdown
    # Heading 1

    Text

    ## Heading 2

    ### Heading 3
    ```

### Heading Attributes

Attributes are preserved and formatted:

Input
:   ```markdown
    ## Heading with classes{.important  .highlight }
    ```

Output
:   ```markdown
    ## Heading with classes {.important .highlight}
    ```

### Setext Headings

Setext-style headings are converted to ATX style.

Input

:   ```markdown
    Heading 1
    =========

    Heading 2
    ---------
    ```

Output
:   ```markdown
    # Heading 1

    ## Heading 2
    ```

## Emphasis and Strong

### Basic Formatting

Emphasis markers are consistently normalized o asterisks (`*`) for italics and
double asterisks (`**`) for bold. Underscores are converted to asterisks.
Ambiguous cases are resolved by escaping emphasis markers to avoid idempotency
issues.

Input
:   ```markdown
    Single asterisks: *italic text*

    Single underscores: _italic text_

    Double asterisks: **bold text**

    Double underscores: __bold text__

    **foo*
    ```

Output
:   ```markdown
    Single asterisks: *italic text*

    Single underscores: *italic text*

    Double asterisks: **bold text**

    Double underscores: **bold text**

    \*\*foo\*
    ```

## Code

### Inline Code

Inline code is preserved with minimal backticks needed:

Input
:   ````markdown
    Code with spaces: ` code with spaces `

    `` ```r ``
    ````

Output
:   `````markdown
    Code with spaces: `code with spaces`

    ```` ```r ````
    `````

### Tab Stops in Code

Tabs in regular text are always normalized to spaces. To preserve tabs in
literal code spans and code blocks, set:

```toml
[format]
tab-stops = "preserve"
tab-width = 4
```

### Fenced Code Blocks

Fenced code blocks are formatted with consistent fencing and attributes. We
normalize them to the *shortcut* style from Pandoc.

Input
:   ````markdown
    ```haskell
    qsort [] = []
    ```

    ``` {.haskell}
    qsort [] = []
    ```

    ```haskell {.numberLines}
    qsort [] = []
    ```

    ``` {.haskell .numberLines}
    qsort [] = []
    ```
    ````

Output
:   ````markdown
    ```haskell
    qsort [] = []
    ```

    ```haskell
    qsort [] = []
    ```

    ```haskell {.numberLines}
    qsort [] = []
    ```

    ```haskell {.numberLines}
    qsort [] = []
    ```
    ````

### Indented Code Blocks

Indented code blocks are normalized to fenced code blocks for consistency:

Input
:   ```markdown
        a <- 1
        b <- a^2
    ```

Output
:   ````markdown
    ```
    a <- 1
    b <- a^2
    ```
    ````

## Lists

### Unordered Lists

Bullet list markers are standardized to `-` for consistency. Indentation is
normalized to 2 spaces per level. Loose lists are converted to tight lights if
they only contain plain (non-block/paragraph) items.

Input
:   ```markdown
    * Item 1
      + Nested item
          *  Deeply nested

     +  Item 2
    ```

Output:
:   ```markdown
    - Item 1
      - Nested item
        - Deeply nested
    - Item 2
    ```

### Ordered Lists

Ordered lists maintain proper numbering:

```markdown
1. First item
2. Second item
   1. Nested item
   2. Another nested
3. Third item
```

### Task Lists

GitHub-style task lists use the standardized `-` marker, and indent to the start
of the text.

Input
:   ```markdown
    + [ ] Parent task
       *   [ ] Nested unchecked task
       - [x]   Nested checked task
    - [X] Another parent task
    ```

Output
:   ```markdown
    - [ ] Parent task
           - [ ] Nested unchecked task
           - [x] Nested checked task
    - [x] Another parent task
    ```

### Definition Lists

Definition lists are indented with three spaces after the marker, flush the
marker to the left, and indent following lines to four spaces.

Input
:   ```markdown
    Term 1

    : Definition 1

    Term 2
    :   Definition 2a
     : Definition 2b

    Term 3
    : Definition
    with lazy continuation
    ```

Output
:   ```markdown
    Term 1

    :   Definition 1

    Term 2
    :   Definition 2a
    :   Definition 2b

    Term 3
    :   Definition with lazy continuation
    ```

### Fancy lists

Fancy lists are indented to line up with the first character of the list item
text.

Input
:   ```markdown
    (i) Parens style
    (ii) Second item
    (iii) Third item

    iv. Starting at four
    v. Five
    vi. Six
    vii. Seven
    viii. Eight
    ix. Nine
    x. Ten
    ```

Output
:   ```markdown
      (i) Parens style
     (ii) Second item
    (iii) Third item

      iv. Starting at four
       v. Five
      vi. Six
     vii. Seven
    viii. Eight
      ix. Nine
       x. Ten
    ```

## Blockquotes

Blockquotes are formatted with consistent `>` markers:

Input
:   ```markdown
    >This is a block quote. This
    >paragraph has two lines.
    >
    > 1. This is a list inside a block quote.
    > 2. Second item.

    > This is a block quote. This
    paragraph has two lines.
    ```

Output
:   ```markdown
    > This is a block quote. This paragraph has two lines.
    >
    > 1. This is a list inside a block quote.
    > 2. Second item.

    > This is a block quote. This paragraph has two lines.
    ```

## Tables

Panache supports all Pandoc table types and normalizes alignment and spacing
while preserving content and attributes.

### Pipe Tables

```markdown
| Header 1 | Header 2 | Header 3 |
|----------|----------|----------|
| Cell 1   | Cell 2   | Cell 3   |
| Cell 4   | Cell 5   | Cell 6   |
```

### Grid Tables

```markdown
+----------+----------+----------+
| Header 1 | Header 2 | Header 3 |
+==========+==========+==========+
| Cell 1   | Cell 2   | Cell 3   |
+----------+----------+----------+
| Cell 4   | Cell 5   | Cell 6   |
+----------+----------+----------+
```

### Simple Tables

We normalize simple tables so that cell contents align with the alignment
specified in the header row, and spacing within cells is normalized.

Input
:   ```markdown
       Right     Left     Center     Default
     -------     ------ ----------   ---------------
          12       12      12            12
       123       123       123          123
           1     1        1             1

       :  A caption
    ```

Output
:   ```markdown
      Right     Left     Center     Default
    -------     ------ ----------   -------
         12     12         12       12
        123     123       123       123
          1     1          1        1

    Table: A caption
    ```

## Math

### Inline Math

Inline math is (currently) untouched.

### Display Math

Display math is formatted on its own lines with leading indentation depending on
the `math-indent` configuration option (default 0):

Input
:   ```markdown
    $$E = mc^2$$
    ```

Output
:   ```markdown
    $$
    E = mc^2
    $$
    ```

## Links

### Inline L

For links, Panache preserves the original link text and URL but normalizes the
spacing around attributes, quotes, and parentheses. Descriptions are wrapped if
reflow wrapping is enabled.

Input
:   ```markdown
    [URL and title](/url/ "title").

    [URL and title](/url/  "title preceded by two spaces").

    [URL and title](/url/   "title preceded by a tab").

    [URL and title](/url/ "title with "quotes" in it")

    [URL and title](/url/ 'title with single quotes')
    ```

Output
:   ```markdown
    [URL and title](/url/ "title").

    [URL and title](/url/ "title preceded by two spaces").

    [URL and title](/url/ "title preceded by a tab").

    [URL and title](/url/ "title with "quotes" in it")

    [URL and title](/url/ "title with single quotes")
    ```

## Fenced Divs

Fenced divs are normalized so that there is no blank line between the opening
fence and the content and no space between the closing fence and the content.
Attributes are preserved and normalized. With nested divs, the inner div

Input
:   ```markdown
    ::: Warning ::::::
    This is a warning.

    ::: Danger
    This is a warning within a warning.
    :::
    ::::::::::::::::::
    ```

Output

:   ```markdown
    ::: Warning
    This is a warning.

    ::::: Danger
    This is a warning within a warning.
    :::::
    :::
    ```

## Footnotes

### Inline Footnotes

```markdown
Text with footnote^[This is the footnote content].
```

### Reference Footnotes

```markdown
Text with reference footnote[^1].

[^1]: This is the footnote content.
```

## Citations

Pandoc citation syntax is preserved:

```markdown
See @smith2020 for more details.
Multiple citations [@smith2020; @jones2021].
Citation with prefix [see @smith2020, pp. 10-15].
```

## Raw Blocks

### HTML

````markdown
```{=html}
<div class="custom">
  <p>Raw HTML content</p>
</div>
```
````

### LaTeX

````markdown
```{=latex}
\begin{equation}
E = mc^2
\end{equation}
```
````

## Horizontal Rulers

Horizontal rulers are normalized to hyphens and extend to `line-width`.

Input
:   ```markdown
    ---
    ***
    ___
    ```

Output (`line-width = 60`):
:   ```markdown
    -----------------------------------------------------------

    -----------------------------------------------------------

    -----------------------------------------------------------
    ```

## Blank Lines

### Collapsing

By default, multiple blank lines are collapsed to one:

**Input:**

```markdown
Paragraph 1


Paragraph 2
```

**Output:**

```markdown
Paragraph 1

Paragraph 2
```

### Preserving Blank Lines

Configure to preserve blank lines:

```toml
[format]
blank-lines = "preserve"
```

`collapse`
:   Collapse multiple blank lines into one (default)

`preserve`
:   Keep all existing blank lines

## Frontmatter

### YAML

YAML frontmatter is parsed and normalized by
[`pretty_yaml`](https://github.com/g-plane/pretty_yaml).

```markdown
---
echo:    false
list:
  -  a
  -     b
---
Text
```

Output
:   ```markdown
    ---
    echo: false
    list:
      - a
      - b
    ---

    Text
    ```

By default this means spacing and list indentation are normalized in the
frontmatter block. This frontmatter formatting is always handled internally by
Panache. The YAML parser/formatter implementation is shipped in Panache-owned
workspace crates.

### Pandoc Title Block

Pandoc-style title blocks are also supported:

```markdown
% My Document Title
% Author Name
% 2026-02-11

Document content starts here.
```

## Best Practices

Use consistent line width
:   Set `line-width` based on your editor width

Enable external formatters
:   Let language-specific tools format code blocks

Choose appropriate flavor
:   Match your document type (`quarto`, `rmarkdown`, etc.)

Test incrementally
:   Format small sections first to understand behavior

Use version control
:   Always commit before formatting large documents

## Ignore Directives

You can selectively disable formatting for specific regions using HTML comment
directives:

### Ignore Formatting Only

Use `panache-ignore-format-start` and `panache-ignore-format-end` to preserve
specific formatting:

```markdown
Normal paragraph will be wrapped and formatted.

<!-- panache-ignore-format-start -->
This    paragraph   has    custom     spacing
that  will   be   preserved   exactly.
<!-- panache-ignore-format-end -->

Back to normal formatting.
```

This is useful for:

- ASCII art or diagrams
- Tables with specific spacing
- Pre-formatted text blocks
- Code examples that aren't in code blocks

### Ignore Both Formatting and Linting

Use `panache-ignore-start` and `panache-ignore-end` to disable both formatting
and linting:

```markdown
<!-- panache-ignore-start -->
#### Heading with unusual spacing
Custom    formatting   and   linting   rules   ignored
<!-- panache-ignore-end -->
```

### Nested Structures

Ignore directives work inside lists, blockquotes, and other nested structures:

```markdown
- List item 1
- List item 2
  <!-- panache-ignore-format-start -->
  Nested    content   with    custom   spacing
  <!-- panache-ignore-format-end -->
- List item 3
```

See [Linting](linting.qmd) for information about linting-specific ignore
directives.
