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