Skip to content

Fence

Adds labels, secondary labels, environment classes, and line prefixes to fenced code blocks. All fence features are coordinated through a single extension to avoid ordering issues.

Usage

Load markwright.fence alongside pymdownx.superfences and pymdownx.highlight; the fence postprocessor rewrites the code-block HTML those produce.

import markdown

md = markdown.Markdown(
    extensions=[
        "pymdownx.superfences",
        "pymdownx.highlight",
        "markwright.fence",
    ],
    extension_configs={
        "markwright.fence": {
            "allowed_environments": ["local", "second", "third", "fourth", "fifth"],
        },
    },
)
Option Default Description
allowed_environments omitted (allow all) List of allowed environment names. Omit it to allow every name; an empty list allows none and emits a ConfigWarning.
label_class code-label CSS class for the label div.
secondary_label_class secondary-code-label CSS class for the secondary label div.

All three options apply the same way in-process, through mw render, and through the mw pre | renderer | mw post pipeline.

Directives work in any fenced code block CommonMark recognizes, including a fence indented up to three spaces or one nested inside a list item. An unclosed fence is not a code block, so its directives are left as text.

See Using with MkDocs to load it in a MkDocs site.

Labels

Add a label above a code block with [label TEXT] as the first line inside the fence:

```python
[label app.py]
from flask import Flask

app = Flask(__name__)
```
app.py
from flask import Flask

app = Flask(__name__)

Secondary Labels

Add a secondary label inside the code block with [secondary_label TEXT]:

```
[secondary_label Output]
Hello, world!
```
Output
Hello, world!

Both Labels Together

```python
[label app.py]
[secondary_label Output]
Hello from Flask!
```
app.py
Output
Hello from Flask!

Environments

Tint the whole code block with a color using [environment NAME] inside the fence. This helps distinguish code blocks for different server environments:

```
[environment local]
ssh user@local-server
```
ssh user@local-server
```
[environment second]
ssh user@staging-server
```
ssh user@staging-server
```
[environment third]
ssh user@production-server
```
ssh user@production-server

Line Prefixes

Prefix flags go in the info string (after the backticks). They wrap each code line in <ol><li> with a data-prefix attribute.

Line Numbers

```line_numbers,python
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello!"
```
  1. from flask import Flask
  2. app = Flask(__name__)
  3. @app.route("/")
  4. def hello():
  5. return "Hello!"

Command Prefix ($)

Implicitly sets the language to bash:

```command
sudo apt update
sudo apt install nginx
```
  1. sudo apt update
  2. sudo apt install nginx

Super User Prefix (#)

Implicitly sets the language to bash:

```super_user
systemctl restart nginx
```
  1. systemctl restart nginx

Custom Prefix

Implicitly sets the language to bash. Use \s for spaces:

```custom_prefix(mysql>)
SELECT * FROM users;
SHOW TABLES;
```
  1. SELECT * FROM users;
  2. SHOW TABLES;

Full Combination

All features can be combined:

```command
[environment local]
[label server.sh]
ssh root@192.168.1.1
apt update && apt upgrade -y
```
server.sh
  1. ssh root@192.168.1.1
  2. apt update && apt upgrade -y