1[:octicons-file-code-24:][_superfences]{: .source-link }
2
3# SuperFences
4
5## Overview
6
7SuperFences provides a number of features:
8
91. Allowing the [nesting of fences](#nested-fence-format) under blockquotes, lists, or other block elements (see
10  [Limitations](#limitations) for more info).
112. Ability to specify [custom fences](#custom-fences) to provide features like flowcharts, sequence diagrams, or other
12  custom blocks.
133. Allow disabling of indented code blocks in favor of only using the fenced variant (off by default).
144. Experimental feature that preserves tabs within a code block instead of converting them to spaces which is Python
15  Markdown's default behavior.
16
17!!! danger "Reminder"
18    Remember to read the [Usage Notes](../usage_notes.md) for information that may be relevant when using this
19    extension!
20
21The SuperFences extension can be included in Python Markdown by using the following:
22
23```py3
24import markdown
25md = markdown.Markdown(extensions=['pymdownx.superfences'])
26```
27
28## Nested Fence Format
29
301. Start and end fence boundaries are specified with either 3 or more backticks or tildes.
31
322. Start and end fence boundaries must both use matching symbols (backticks or tildes) and must be of the same number of
33  symbols.  If start is 3 backticks, the fence will end with 3 backticks.
34
353. Start and end fence boundaries must be aligned to the same indentation level.
36
374. Content between fences must be indented at least the same amount as the start and end boundaries.  Empty lines are
38  exempted.
39
405. If you are using a fenced block inside a blockquote, at the very least, the first line of the fenced block needs to
41  have the appropriate number of `>` characters signifying the quote depth.
42
43    ````
44    > ```
45      a fenced block
46      ```
47    ````
48
496. Too many blank lines will cause a blockquote to terminate, so remember to use `>` markers accordingly if not marking
50  every line.
51
52    ````
53    > ```
54      a fenced block
55
56    > with blank lines
57      ```
58    ````
59
607. If using a fenced block as the first line of a list, you will have to leave the first line blank, but remember that
61  the list marker must be followed by a space.
62
63    ````
64    -<space>
65        ```
66        a fenced block
67        ```
68
69    Definition
70    :<space>
71        ```
72        a fenced block
73        ```
74    ````
75
768. Fenced blocks should be separated from other blocks by an empty line.
77
78    ````
79    Paragraph.
80
81    ```
82    a fenced block
83    ```
84
85    Another paragraph.
86    ````
87
88## Injecting Classes, IDs, and Attributes
89
90You can use the brace format to specify classes and IDs. The first provided class is always used as the language class.
91IDs (`#id`) can also be inserted as well. Arbitrary attributes in the form `key="value"` can be inserted as well if
92the [`attr_list`][attr-list] extension is enabled, but when using Pygments, only `key="value"` attributes that start
93with the `data-` prefix will be recognized, all others will be treated as options for Pygments and will be rejected if
94not valid.
95
96!!! example "Injecting Classes"
97
98    === "HTML"
99        ```html
100        <table class="extra-class highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span>1</pre></div></td><td class="code"><div class="extra-class highlight"><pre><span></span><code><span cv></td><td class="code"><div class="extra-class highlight"><pre><span></span><code><span class="kn">import</span> <spanlass="kn">import</span> <span class="nn">hello_world</span>\n</code></pre></div>\n</td></tr></table>
101        ```
102
103    === "Markdown"
104        ````
105        ```{.python .extra-class linenums="1"}
106        import hello_world
107        ```
108        ````
109
110When generating additional classes on a JavaScript style code block (non-Pygments code blocks), classes are injected in
111the `#!html code` block.
112
113!!! example "Non-Pygments Injecting Classes"
114
115    === "HTML"
116        ```html
117        <pre id="id" class="highlight"><code class="extra-class language-python linenums">import hello_world</code></pre>
118        ```
119
120    === "Markdown"
121        ````
122        ```{.python .extra-class #id linenums="1"}
123        import hello_world
124        ```
125        ````
126
127When using Pygments, all extra classes and attributes will be attached to the Pygments' wrapper `#!html <div>`.
128
129When using a built in [custom formatter](#custom-fences), all classes and IDs are injected on to the first element
130`#!html <div>` or `#!html <pre>`. This preserves previous behavior, but you can write your own and inject them in the
131way that suites your needs.
132
133!!! new "New 9.0"
134    Added support for `#id` in Pygments brace headers. Also added support for arbitrary `data-` attributes if the
135    [`attr_list`][attr-list] extension is enabled.
136
137## Preserve Tabs
138
139Python Markdown has an approach where it normalizes whitespace. This means `\r\n` is converted to `\n` and `\t` is
140converted to spaces. In 99% of Markdown, this is never really an issue, but with code blocks it can be. Tabs can
141sometimes be very useful for aligning certain kinds of data, especially when dealing with characters of varying width.
142
143!!! example "Tabs in Content"
144
145    === "Output"
146        ```
147        ============================================================
148        T	Tp	Sp	D	Dp	S	D7	T
149        ------------------------------------------------------------
150        A	F#m	Bm	E	C#m	D	E7	A
151        A#	Gm	Cm	F	Dm	D#	F7	A#
152        B♭	Gm	Cm	F	Dm	E♭m	F7	B♭
153        ```
154
155    === "Markdown"
156        ````
157        ```
158        ============================================================
159        T	Tp	Sp	D	Dp	S	D7	T
160        ------------------------------------------------------------
161        A	F#m	Bm	E	C#m	D	E7	A
162        A#	Gm	Cm	F	Dm	D#	F7	A#
163        B♭	Gm	Cm	F	Dm	E♭m	F7	B♭
164        ```
165        ````
166
167If you have a scenario where preserving tabs is a requirement, you can use SuperFences `preserve_tabs` option to prevent
168converting tabs to spaces inside fenced code blocks. This *only* applies to fenced code blocks. Indented code blocks and
169inline code blocks will still be treated with Python Markdown's default behavior.
170
171This feature is experimental and actually applies the fences before whitespace normalization and bypasses the
172normalization for the code content.
173
174## Code Highlighting
175
176Assuming Pygments is installed, code highlighting will be handled by [Pygments][pygments] by default. If Pygments is not
177installed, or disabled, code blocks will be created using HTML5 style tags for a JavaScript syntax highlighter:
178`#!html <pre class="highlight"><code class="language-mylanguage"></code></pre>`. If you disable `highlight_code`,
179specified languages will be ignored, and the content will be wrapped in a simple `pre` and `code` tags with no classes.
180
181Highlighting can be further controlled via the [`pymdownx.highlight`](./highlight.md) extension.
182
183When using fenced code blocks, you can specify a specific syntax language to highlight with by specifying the language
184name directly after the opening tokens (either ` ``` ` or `~~~`). Whether using Pygments or some other JavaScript
185highlighter, the syntax is the same, but please consult your highlighter's documentation for recognized language syntax
186specifiers.
187
188!!! example "Highlight Example"
189
190    === "Output"
191        ```py3
192        import foo.bar
193        ```
194
195    === "Markdown"
196        ````
197        ```py3
198        import foo.bar
199        ```
200        ````
201
202## Showing Line Numbers
203
204Line numbers are provided via Pygments and can either be shown per code block or globally for all. To show globally via
205[`pymdownx.highlight`](./highlight.md), you must set `linenums` to `#!py3 True` in the respective extension.
206
207To set line numbers per code block, you can specify a special setting directly after the opening tokens (and language if
208present). Simply specify the starting line line number with option `linenums="1"`. The setting is followed by the equal
209sign and the value must be quoted.  Valid line numbers are n > 0.  If `linenums` is enabled globally, this will just
210control the starting line shown in the block.
211
212!!! example "Line Number Example"
213
214    === "Output"
215        ``` {linenums="1"}
216        import foo.bar
217        ```
218
219    === "Markdown"
220        ````
221        ``` {linenums="1"}
222        import foo.bar
223        ```
224        ````
225
226And, if we wanted to start with a different starting line number, we would just specify something other than `1`.
227
228!!! example "Custom Line Number Start Example"
229
230    === "Output"
231        ``` {linenums="2"}
232        import foo.bar
233        ```
234
235    === "Markdown"
236        ````
237        ``` {linenums="2"}
238        import foo.bar
239        ```
240        ````
241
242Pygments also has a few additional options in regards to line numbers. One is "line step" which, if set to a number n >
2431, will print only every n^th^ line number. The other option is a setting that can mark line numbers as "special" with a
244span and class `special`. If the special parameter is set to a number n > 0, every n^th^ line number is given the CSS
245class `special`.
246
247So to set showing only every other line number, we could do the following. Line options are separated by a space, and
248"line step" is always the second option, so you must specify line start before line step.
249
250!!! example "Nth Line Example"
251
252    === "Output"
253        ``` {linenums="1 2"}
254        """Some file."""
255        import foo.bar
256        import boo.baz
257        import foo.bar.baz
258        ```
259
260    === "Markdown"
261        ````
262        ``` {linenums="1 2"}
263        """Some file."""
264        import foo.bar
265        import boo.baz
266        import foo.bar.baz
267        ```
268        ````
269
270To set every other line as special, you must set the third `linenums` option (specify line start and step before it).
271Special must be a value of n > 0. Additionally, you can set this globally with `linenums_special` in the
272[Highlight extension](./highlight.md).
273
274!!! example "Special Line Example"
275
276    === "Output"
277        ``` {linenums="1 1 2"}
278        """Some file."""
279        import foo.bar
280        import boo.baz
281        import foo.bar.baz
282        ```
283
284    === "Markdown"
285        ````
286        ``` {linenums="1 1 2"}
287        """Some file."""
288        import foo.bar
289        import boo.baz
290        import foo.bar.baz
291        ```
292        ````
293
294For JavaScript libraries, a class of `linenums` is written to the block.  This may or may not be leveraged by your
295chosen highlighter.  It is uncertain at this time whether line number support for JavaScript highlighters will be
296enhanced beyond this.w what to inject.
297
298## Highlighting Lines
299
300Via Pygments, certain lines can be specified for highlighting.  This is done by specifying a special setting directly
301after the opening tokens (and language if present).  The setting is named `hl_lines` and the value should be the
302targeted line numbers separated by spaces.
303
304!!! example "Highlight Lines Example"
305
306    === "Output"
307        ```{.py3 hl_lines="1 3"}
308        """Some file."""
309        import foo.bar
310        import boo.baz
311        import foo.bar.baz
312        ```
313
314    === "Markdown"
315        ````
316        ```{.py3 hl_lines="1 3"}
317        """Some file."""
318        import foo.bar
319        import boo.baz
320        import foo.bar.baz
321        ```
322        ````
323
324Line numbers are always referenced starting at 1 ignoring what the line number is labeled as when showing line numbers.
325
326!!! example "Highlight Lines with Line Numbers Example"
327
328    === "Output"
329        ```{.py3 hl_lines="1 3" linenums="2"}
330        """Some file."""
331        import foo.bar
332        import boo.baz
333        import foo.bar.baz
334        ```
335
336    === "Markdown"
337        ````
338        ```{.py3 hl_lines="1 3" linenums="2"}
339        """Some file."""
340        import foo.bar
341        import boo.baz
342        import foo.bar.baz
343        ```
344        ````
345
346If you'd like to do a range of lines, you can use the notation `x-y` where `x` is the starting line and `y` is the
347ending line. You can do multiple ranges and even mix them with non ranges.
348
349!!! example "Highlight Ranges"
350
351    === "Output"
352        ```{.py3 hl_lines="1-2 5 7-8"}
353        import foo
354        import boo.baz
355        import foo.bar.baz
356
357        class Foo:
358           def __init__(self):
359               self.foo = None
360               self.bar = None
361               self.baz = None
362        ```
363
364    === "Markdown"
365        ````
366        ```{.py3 hl_lines="1-2 5 7-8"}
367        import foo
368        import boo.baz
369        import foo.bar.baz
370
371        class Foo:
372           def __init__(self):
373               self.foo = None
374               self.bar = None
375               self.baz = None
376        ```
377        ````
378
379## Code Block Title Headers
380
381!!! new "New 9.0"
382    Title headers are new in version `9.0`.
383
384When Pygments is enabled, a header with a title can be applied with the `title` option. This essentially controls the
385Pygments' `filename` option under the hood. It made more sense to use the term `title` as people can really set any
386arbitrary title, not just filenames.
387
388Pygments will simply output the HTML below. The user is responsible for provided CSS to style the header. Pygments uses
389the class name of `filename` as that is the feature being used under the hood.
390
391```html
392<div class="highlight">
393<span class="filename">Some Title</span>
394<pre><code></code></pre>
395</div>
396```
397
398If using line numbers and the `linenums_style` set to `table` (the default), the title will be inserted in `#!html <th>`
399element at the start of the table set to span both the line number column and the line column.
400
401```html
402<table class="highlighttable">
403<tr>
404  <th colspan="2" class="filename"><div class="highlight"><span class="filename">My title</span></div></th>
405</tr>
406<tr>
407  <td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">1</span></pre></div></td>
408  <td class="code"><div class="highlight"><pre><code></code></pre></div></td>
409</tr>
410</table>
411```
412
413!!! example "Title"
414
415    === "Output"
416        ```{.py3 title="My Cool Header"}
417        import foo.bar
418        import boo.baz
419        import foo.bar.baz
420        ```
421
422    === "Markdown"
423        ````
424        ```{.py3 title="My Cool Header"}
425        import foo.bar
426        import boo.baz
427        import foo.bar.baz
428        ```
429        ````
430
431If the `auto_title` option is enabled in the [Highlight extension](./highlight.md), the title will be auto populated
432with the name of the lexer used to highlight the code (unless `title` is manually specified). In the example below,
433no `title` is specified, but the the title is extracted from the Python lexer.
434
435!!! example "Auto Filename"
436
437    === "Output"
438        ````md-render
439        ---
440        extensions:
441        - pymdownx.highlight
442        - pymdownx.superfences
443
444        extension_configs:
445          pymdownx.highlight:
446            auto_title: true
447        ---
448        ```python
449        import foo.bar
450        import boo.baz
451        import foo.bar.baz
452        ```
453        ````
454
455    === "Markdown"
456        ````
457        ```python
458        import foo.bar
459        import boo.baz
460        import foo.bar.baz
461        ```
462        ````
463
464There may be some cases where a Lexer returns a result that is undesired. For example, when a user specifies the `pycon`
465lexer, the title that is returned is quite verbose.
466
467!!! example "Auto Filename"
468
469    === "Output"
470        ````md-render
471        ---
472        extensions:
473        - pymdownx.highlight
474        - pymdownx.superfences
475
476        extension_configs:
477          pymdownx.highlight:
478            auto_title: true
479        ---
480        ```pycon
481        >>> 3 + 3
482        6
483        ```
484        ````
485
486    === "Markdown"
487        ````
488        ```pycon
489        >>> 3 + 3
490        6
491        ```
492        ````
493
494In a case like above, it may be desired to simply use the title `Python`. We can configure the [Highlight extension](./highlight.md)
495to override any auto returned title. Simply create mapping via the `auto_title_map` specifying the title you wish to
496override as the key, and the desired title as the value.
497
498```py3
499extension_configs = {
500    "pymdownx.highlight": {
501        "auto_title": True,
502        "auto_title_map": {
503            "Python Console Session": "Python"
504        }
505    }
506}
507```
508
509Now whenever we use `pycon`, we get "Python" instead of "Python Console Session".
510
511````md-render
512---
513extensions:
514- pymdownx.highlight
515- pymdownx.superfences
516
517extension_configs:
518  pymdownx.highlight:
519    auto_title: true
520    auto_title_map: {"Python Console Session": "Python"}
521---
522```pycon
523>>> 3 + 3
5246
525```
526````
527
528## Pygments Line Anchors and Spans
529
530!!! new "New 9.0"
531    The various line wrapping options are new to version `9.0`.
532
533Pygments offers a couple of options that will wrap lines, line numbers even create anchor links for line numbers.
534SuperFences, when using Pygments, exposes these options under similar names.
535
536In this example, we will wrap each line of code in a span. Pygments will create an ID for each span using the prefix
537that we provide. We simply set the global config option `line_spans` and specify the desired "prefix" (`_codeline`), and
538then every line will be wrapped in a span with the ID `prefix-x-y` where `prefix` is the user specified prefix, `x` is a
539unique number for the code block, and `y` is the line number. After that, it is up to the user to do as they with to
540target the ID with either JavaScript and/or CSS.
541
542=== "Config"
543
544    ```py3
545    extension_configs = {
546        "pymdownx.highlight": {
547            'linenums_style': 'inline',
548            'line_spans': '__codeline'
549        }
550    }
551    ```
552
553=== "Markdown"
554    ````
555    ```{.python linenums="1 1" }
556    import foo
557    ```
558    ````
559
560=== "HTML"
561    ```html
562    <div class="highlight">
563    <pre>
564    <span></span>
565    <code>
566    <span id="__codeline-0-1"><span class="linenos">1</span><span class="kn">import</span> <span class="nn">foo</span>
567    </span>
568    </code>
569    </pre>
570    </div>
571    ```
572
573We can also wrap line numbers with with a link and inject anchors so you can click line numbers and be taken to said
574line. To do this, `anchor_linenums` must be enabled and then a prefix should be provided via `line_anchors`, just like
575`line_spans`, `line_anchors` will produce an ID in the form `prefix-x-y` where `x` is a unique number for the code block
576and `y` is the line number. If you wish to not have the line numbers clickable, and just have the anchors inserted,
577you can omit enabling `anchor_linenums`.
578
579=== "Config"
580
581    ```py3
582    extension_configs = {
583        "pymdownx.highlight": {
584            'linenums_style': 'inline',
585            'line_spans': '__codeline',
586            'line_anchors': '__codelineno',
587            'anchor_linenums': True
588        }
589    }
590    ```
591
592=== "Markdown"
593    ````
594    ```{.python linenums="1 1" }
595    import foo
596    ```
597    ````
598
599=== "HTML"
600    ```html
601    <div class="highlight">
602    <pre>
603    <span></span>
604    <code>
605    <span id="__codeline-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1"></a><a href="#__codelineno-0-1"><span class="linenos">1</span></a><span class="kn">import</span> <span class="nn">foo</span>
606    </span>
607    </code>
608    </pre>
609    </div>
610    ```
611
612## Custom Fences
613
614SuperFences allows defining custom fences for special purposes. For instance, we could create special fences for
615diagrams that we could later run Mermaid on.
616
617!!! example "Flow Chart Example"
618
619    === "Output"
620        ```diagram
621        graph TD
622            A[Hard] -->|Text| B(Round)
623            B --> C{Decision}
624            C -->|One| D[Result 1]
625            C -->|Two| E[Result 2]
626        ```
627
628    === "Markdown"
629        ````
630        ```diagram
631        graph TD
632            A[Hard] -->|Text| B(Round)
633            B --> C{Decision}
634            C -->|One| D[Result 1]
635            C -->|Two| E[Result 2]
636        ```
637        ````
638
639This would allow us access to all the diagrams Mermaid offers. Some Mermaid diagrams are less practical to use as they
640don't scale well, but many work great.
641
642In the above example, we have set up a custom fence called `diagram` which allows us to process special charts with
643[Mermaid][mermaid]. In this case, our special fence preserves the content and sends them to a an element so that
644[Mermaid][mermaid] can then find them and convert them when the document is loaded. To learn more see [UML Diagram
645Example](#uml-diagram-example).
646
647Custom fences are created via the `custom_fences` option.  `custom_fences` takes an array of dictionaries where each
648dictionary defines a custom fence. The dictionaries require the following keys:
649
650Keys        | Description
651----------- | -----------
652`name`      | The language name that is specified when using the fence in Markdown. If given `*`, it will override the base fence logic, the default for all fence names not handled by other custom fences.
653`class`     | The class name assigned to the HTML element when converting from Markdown to HTML.
654`format`    | A function that formats the HTML output. The function should return a string as HTML.
655`validator` | An optional parameter that is used to provide a function to validate custom fence parameters.
656
657!!! warning "Logging"
658    When a custom fence fails, the error will be swallowed up and the error will be handled gracefully. If logging is
659    desired, custom logging should be added into the custom function. SuperFences will not provide any.
660
661!!! new "New in 7.0"
662    Starting in 7.0, you can override the base fence logic (the syntax highlighter) by specifying the custom fence
663    with a name of `*`. This means that if a fence does not match any other custom fences, the default, fallback fence
664    would be handled by your custom `*` fence. This can be useful for tailoring a fence output with custom parameters
665    for a specific, favorite JavaScript highlighter.
666
667### Formatters
668
669SuperFences provides two format functions by default, but you can always write your own:
670
671Format\ Function                | Description
672------------------------------- | -----------
673`superfences.fence_code_format` | Places the HTML escaped content of the fence under a `#!html <pre><code>` block.
674`superfences.fence_div_format`  | Places the HTML escaped content of the fence under a `#!html <div>` block.
675
676In general, formatters take five parameters: the source found between the fences, the specified language, the class name
677originally defined via the `class` option in the `custom_fence` entry, custom options, additional classes defined in
678brace style headers, an optional ID, any attributes defined in the brace style header, and the Markdown object (in case
679you want access to meta data etc.).
680
681```py3
682def custom_formatter(source, language, css_class, options, md, classes=None, id_value='', attrs=None, **kwargs):
683    return string
684```
685
686or
687
688```py3
689def custom_formatter(source, language, css_class, options, md, **kwargs):
690    return string
691```
692
693All formatters should return a string as HTML.
694
695!!! tip "YAML Configuration Format"
696    If you are attempting to configure these options in a YAML based configuration (like in [MkDocs][mkdocs]), please
697    see the [FAQ](../faq.md#function-references-in-yaml) to see how to specify function references in YAML.
698
699!!! new "New 7.0"
700    The addition of the parameters `classes` and `id_value` is new in 7.0. If injecting additional classes or ids via
701    [brace headers](#injecting-classes-and-ids), only then will `classes` and `id_value` be passed in to preserve
702    backwards compatibility with old custom formatters. Users, moving forward, should at the very least update their
703    formatters with `**kwargs` to future proof their custom formatters in case additional parameters are added in the
704    future.
705
706!!! new "Changes 8.0"
707    Formatters now take the keyword parameter `attrs`.
708
709### Validators
710
711The `validator` is used to provide a function that allows the validation of inputs. Inputs are then sorted to either
712`attrs` or `options`. While a `formatter` can treat `attrs` and `options` however they like, the intention is that key
713value pairs assigned to `attrs` are assigned directly to the fenced block's element, while `options` are used to
714conditionally control logic within the formatter. If no validator is defined, the default is used which assigns all
715inputs to `attrs`.
716
717SuperFences will only pass `attrs` to a formatter if an attribute style header is used for a fenced block
718(` ``` {.lang attr="value"}`) and the [`attr_list`][attr-list] extension is enabled. Attribute are not supported in the
719form (` ```lang attr=value`) and will cause the parsing of the fenced block to abort.
720
721Custom options can be used as keys with quoted values (`key="value"`), or as keys with no value (`key`). If a key is
722given with no value, the value will be the key value. SuperFences will parse the options in the fence and then pass them
723to the validator. If the validator returns true, the options will be accepted and later passed to the formatter. `attrs`
724will only be passed to the formatter if the [`attr_list`][attr-list] extension is enabled. `attrs` will also be ignored
725during Pygments highlighting.
726
727Assuming a validator fails, the next `validator`/`formatter` defined will be tried.
728
729For a contrived example: if we wanted to define a custom fence named `test` that accepts an option `opt` that can only
730be assigned a value of `A`, we could define the validator below. Notice that if we get an input that matches `opt`, but
731doesn't validate with the appropriate value, we abort handling the fenced block for this `validator`/`formatter` by
732returning `False`. All other inputs are assigned as `attrs` which will be passed to the formatter if the
733[`attr_list`][attr-list] extension is enabled.
734
735```py3
736def custom_validator(language, inputs, options, attrs, md):
737    """Custom validator."""
738
739    okay = True
740    for k, v in inputs.items():
741        if k == 'opt':
742            if v != "A":
743                okay = False
744                break
745            else:
746                options[k] = v
747        else:
748            attrs[k] = v
749
750    return okay
751```
752
753Assuming validation passed, the formatter would be given the option and any attributes (though the formatter below
754doesn't use the attributes).
755
756```py3
757def custom_format(source, language, class_name, options, md, **kwargs):
758    """Custom format."""
759
760    return '<div class_name="%s %s", data-option="%s">%s</div>' % (language, class_name, options['opt'], html_escape(source))
761```
762
763This would allow us to use the following custom fence:
764
765````
766```{.test opt="A"}
767test
768```
769````
770
771!!! tip "YAML Configuration Format"
772    If you are attempting to configure these options in a YAML based configuration (like in [MkDocs][mkdocs]), please
773    see the [FAQ](../faq.md#function-references-in-yaml) to see how to specify function references in YAML.
774
775!!! new "Changes 8.0"
776    - `validator` now accepts the following variables:
777        - `inputs`: with all the parsed options/attributes (validator should not modify this structure).
778        - `options`: a dictionary to which all valid options should be assigned to.
779        - `attrs`: a dictionary to which all valid attributes should be assigned to.
780        - `md`: the `Markdown` object.
781    - If the [`attr_list`][attr-list] extension is enabled and the brace style header is used, any key/value pairs that
782      were assigned as attributes by the `validator` will be passed to the `formatter`'s `attrs` parameter.
783    - Options in the form of `key=` (which have no value) will are no longer be allowed. A `key` with no value will
784      assume the `value` to be the `key` name. This brings consistency as options are now parsed with
785      [`attr_list`][attr-list].
786    - If a `validator` fails, the next `validator`/`formatter` pair will be tired.
787
788### UML Diagram Example
789
790!!! warning "Support"
791
792    This example is mainly used to illustrate how custom fences work. While Mermaid is used in the example, it is the
793    bare minimum needed to get diagrams working.
794
795    Please reference [Mermaid's][mermaid] documents for more information on configuring features. PyMdown Extensions
796    does not offer direct support for issues you may have in using [Mermaid][mermaid], feel free to use their issue
797    tracker to report problems with their library.
798
799    We do provide some [advanced notes on Mermaid](../extras/mermaid.md) if you are interested in learning how we use
800    and configure it in our own documentation.
801
802This example illustrates how you can use the `custom_fences` option to do UML diagrams with [Mermaid][mermaid]. The
803settings below show us creating a new custom fence called `mermaid`. The special fence is set under the `custom_fences`
804[option](#options).
805
806The `mermaid` fences will pass the content through the `superfences.fence_div_format` format function which will wrap
807the content in `#!html <div>` blocks and attach the class `mermaid` to the `#!html <div>` block.
808
809```py3
810extension_configs = {
811    "pymdownx.superfences": {
812        "custom_fences": [
813            {
814                'name': 'diagram',
815                'class': 'diagram',
816                'format': pymdownx.superfences.fence_div_format
817            }
818        ]
819    }
820}
821```
822
823This would allow a user to create fenced blocks with the `mermaid` specifier:
824
825````
826```mermaid
827...content here
828```
829````
830
831The format function we used in this example only escapes the content to be included in HTML. We will rely on the
832[Mermaid][mermaid] JavaScript library to render our flowcharts/diagrams in the browser. [Mermaid][mermaid], on load,
833will automatically find the `#!html <div>` elements with the `mermaid` class and render them. We can include
834[Mermaid][mermaid] via its CDN.
835
836```html
837<script src="https://unpkg.com/mermaid@8.6.4/dist/mermaid.min.js"></script>
838```
839
840## Limitations
841
842This extension suffers from some of the same quirks that the original fenced block extension suffers from.  Normally
843Python Markdown does not parse content inside HTML tags unless they are marked with the attribute `markdown='1'`.  But
844since this is run as a preprocessor, it is not aware of the HTML blocks.
845
846SuperFences is made to work with the default extensions out of the box.  It will probably not work with other extensions
847such as Grid Tables, since that extension allows for characters to obscure the blocks like the blockquote syntax does
848(though this has been designed to work with blockquotes).  Ideally fenced blocks need to be handled by a block parser,
849but there is much work to be done on Python Markdown's internal block handlers before this is possible.
850
851SuperFences works best when following the guidelines.  If the guidelines are not followed, odd results may be
852encountered.
853
854For the reasons above, the nested fences feature really is just a workaround.  But for a lot of people, this
855functionality is more than sufficient.
856
857## Options
858
859Option                         | Type         | Default       | Description
860------------------------------ | ------------ | ------------- | -----------
861`css_class`                    | string       | `#!py3 ''`    | Class name is applied to the wrapper element of the code. If configured, this setting will override the `css_class` option of Highlight. If nothing is configured here or in Highlight, the class `highlight` will be used.
862`disable_indented_code_blocks` | bool         | `#!py3 False` | Disables Python Markdown's indented code block parsing.  This is nice if you only ever use fenced blocks.
863`custom_fences`                | [dictionary] | `#!py3 []`    | Custom fences.
864`preserve_tabs`                | bool         | `#!py3 False` | Experimental feature that preserves tabs in fenced code blocks.
865