Skip to content

Snippets

Overview

Not Meant for User Facing Sites

Snippets is meant to make including snippets in documentation easier, but it should not be used for user facing sites that take and parse user content dynamically.

Snippets is an extension to insert markdown or HTML snippets into another markdown file. Snippets is great for situations where you have content you need to insert into multiple documents. For instance, this document keeps all its hyperlinks in a separate file and then includes those hyperlinks at the bottom of a document via Snippets. If a link needs to be updated, it can be updated in one location instead of updating them in multiple files.

Snippets is run as a preprocessor, so if a snippet is found in a fenced code block etc., it will still get processed.

If a snippet declaration is processed, and the specified file cannot be found, then the markup will be removed.

Snippets can handle recursive file inclusion. And if Snippets encounters the same file in the current stack, it will avoid re-processing it in order to avoid an infinite loop (or crash on hitting max recursion depth).

This is meant for simple file inclusion, it has no intention to implement features from complex template systems. If you need something more complex, you may consider using a template environment to process your files before feeding them through Python Markdown. If you are using a document generation system, this can likely be performed via a plugin for that document system (assuming a plugin environment is available).

The Snippets extension can be included in Python Markdown by using the following:

import markdown
md = markdown.Markdown(extensions=['pymdownx.snippets'])

Snippets Notation

There are two modes of inserting snippets: single line and block. Single line mode accepts a single file name, and block accepts multiple files. Snippets does not require a specific extension, and as long as a valid file name is specified, it will attempt to process it.

Snippets paths are relative to base location, by default the current working directory. You can specify a new base location by setting the base_path. You can even allow downloading snippets from external locations. To learn more, check out "Specifying Snippet Locations" and "URL Snippets".

Single Line Format

Single line format is done by placing the following markup for the single line notation:

--8<-- "filename.ext"

As you can see, the notation is ASCII scissors cutting a line followed by the file name. In the case of the single line variant, the file name follows directly after the scissors and is quoted. In the case of the block format, the file names follow on separate lines and an additional scissor is added afterwards to signal the end of the block.

The dashes can be as few as 1 (-8<-) or longer if desired (---8<---------); whatever your preference is. The important thing is that the notation must reside on a line(s) by itself, and the path, must be quoted in the case of the single line notation. If the file name is indented, the content will be indented to that level as well.

You can temporarily disable the snippet by placing a ; before the file name:

--8<-- "; skip.md"

Block Format

The second approach is known as the block format. Block format allows you to insert multiple files.

--8<--
filename.md
filename.log
--8<--
The block format differs from the single format by requiring the content to be fenced between two --8<--. The start and end --8<-- must be on a line by themselves.

When using the block format empty lines are also preserved within the block. Consider the example below.

--8<--
fileA.md

fileB.md
--8<--

This would yield:

Content of file A.

Content of file B.

If you have a file you want to temporarily ignore, you can comment it out by placing a ; at the start of the line.

--8<--
include.md
; skip.md
--8<--

Snippet Lines

New 9.6

When specifying a snippet, you can specify which lines of the Snippet file that you wish to include. To specify line numbers, simply append the start and/or end to the end of the file name with each number separated with :.

  • To specify extraction of content to start at a specific line number, simply use file.md:3.
  • To extract all content up to a specific line, use file.md::3. This will extract lines 1 - 3.
  • To extract all content starting at a specific line up to another line, use file.md:4:6. This will extract lines 4 - 6.
--8<-- "file.md:4:6"

--8<--
include.md::3
--8<--

Snippet Sections

New 9.7

Specifying snippet lines may not always be ideal. The source could change by moving, adding, and/or removing lines. A way around this is to partition a snippet into named sections and then targeting a specific section to be included instead of specific line numbers.

Snippet sections can be specified by surrounding a block of text with --8<-- [start:name] and --8<-- [end:name]. Then a file can simply specify the snippet using the name instead of line numbers.

--8<-- "include.md:name"

--8<--
include.md:name
--8<--

Unlike other snippet syntax, the section start and end syntax do not have to be on a line by themselves. This allows you to embed them in comments depending on the file type. When a section is included, the line with the start and end are always omitted.

If we wanted to include a function from a Python source, we could specify the snippet as follows:

# --8<-- [start:func]
def my_function(var):
    pass
# --8<-- [end:func]

And then just include it in our document:

--8<-- "example.py:func"

Escaping Snippets Notation

New 9.6

If it is necessary to demonstrate the snippet syntax, an escaping method is required. If you need to escape snippets, just place a ; right before -8<-. This will work for both single line and block format. An escaped snippet notation will be passed through the Markdown parser with the first ; removed.

Escaped Snippets
```
;--8<-- "escaped.md"
;;--8<-- "escaped.md"
```
--8<-- "escaped.md"
;--8<-- "escaped.md"

Legacy Escaping

The legacy escape method required placing a space at the end of the line with -8<-, while this should still work, this behavior will be removed at sometime in the future and is discouraged.

Specifying Snippet Locations

All snippets are specified relative to the base path(s) specified in the base_path option. base_path is a list of paths (though it will take a single string for legacy purposes).

When evaluating paths, they are done in the order specified. The specified snippet will be evaluated against each base path and the first base path that yields a valid snippet will be returned.

If a base path is a file, the specified snippet will be compared against the base name of that file. For instance, if we specified a snippet of test.md and we had a base_path of ["some/location/test.md"], this would match. A specified snippet of location/test.md would not match. This is great if you have a one off file outside of your base directory, but you'd like to directly include it.

URL Snippets

URLs, if url_download is enabled, can also be used as snippets. Instead of using a file, simply specify a URL in its place. By default, a max size for content is specified with url_max_size and a default timeout via url_timeout. If either of these is set to zero, the limits will be ignored.

To pass arbitrary HTTP headers in every HTTP request use url_request_headers.

Nested Snippets

One thing to note though, if a snippet is included via a URL, all nested snippets within it must also be URLs. URL snippets are not allowed to reference local snippet files.

New 9.5

URL snippet support was introduced in 9.5.

Dedent Subsections

New 9.10

Experimental

By default, when a subsection is extracted from a file via the section notation or the lines notation, the content is inserted exactly how it is extracted. Unfortunately, sometimes you are extracting an indented chunk, and you do not intend for that chunk to be indented.

dedent_subsections is a recent option that has been added to see if it alleviates the issue. When specifying a subsection of a file to insert as a snippet, via "sections" or "lines", that content will have all common leading whitespace removed from every line in text.

Depending on how the feature is received, it may be made the default in the future.

Auto-Append Snippets

Snippets is designed as a general way to target a file and inject it into a given Markdown file, but some times, especially when building documentation via a library like MkDocs, it may make sense to provide a way to append a given file to every Markdown document without having to manually include them via Snippet syntax in each page. This is especially useful for including a page of reference links or abbreviations on every page.

Snippets provides an auto_append option that allows a user to specify a list of files that will be automatically appended to every to Markdown content. Each entry in the list searched for relative to the base_path entries.

Options

Option Type Default Description
base_path [string] ['.'] A list of strings indicating base paths to be used resolve snippet locations. For legacy purposes, a single string will also be accepted as well. Base paths will be resolved in the order they are specified. When resolving a file name, the first match wins. If a file name is specified, the base name will be matched.
encoding string 'utf-8' Encoding to use when reading in the snippets.
check_paths bool False Make the build fail if a snippet can't be found.
auto_append [string] [] A list of snippets (relative to the base_path) to auto append to the Markdown content.
url_download bool False Allows URLs to be specified as file snippets. URLs will be downloaded and inserted accordingly.
url_max_size int 33554432 Sets an arbitrary max content size. If content length is reported to be larger, and exception will be thrown. Default is ~32 MiB.
url_timeout float 10.0 Passes an arbitrary timeout in seconds to URL requestor. By default this is set to 10 seconds.
url_request_headers {string:string} {} Passes arbitrary headers to URL requestor. By default this is set to empty map.
dedent_subsections bool False Remove any common leading whitespace from every line in text of a subsection that is inserted via "sections" or by "lines".
restrict_base_path bool True Ensure that the specified snippets are children of the specified base path(s). This prevents a path relative to the base path, but not explicitly a child of the base path.