Content Reuse Directives

Reference for content reuse directives (include, literalinclude)

3 min read 679 words

Content reuse directives allow you to include external files directly in your markdown content, enabling a "Write Once, Publish Everywhere" strategy.

See also: Content Reuse for detailed strategies, best practices, and common patterns.

Key Terms

Include Directive
A directive ({include}) that includes markdown files directly in your content. Supports line ranges and relative path resolution.
Literal Include Directive
A directive ({literalinclude}) that includes code files as syntax-highlighted code blocks. Auto-detects language from file extension and supports line ranges, emphasis, and line numbers.
Snippet
A reusable content file (typically markdown or code) that can be included in multiple pages. Organized in dedicated directories likecontent/snippets/.
Path Resolution
The process of finding included files. Bengal resolves paths relative to the current page's directory first, then falls back to the site root.
Path Traversal Prevention
Security feature that prevents including files outside the site root. Blocks../sequences and absolute paths to protect against unauthorized file access.

Include

Include markdown files directly in your content.

Syntax:

1
2
:::{include} path/to/file.md
:::

With Options:

1
2
3
4
:::{include} path/to/file.md
:start-line: 5
:end-line: 20
:::

Options:

  • :start-line:- Starting line number (1-indexed)
  • :end-line:- Ending line number (1-indexed)

Path Resolution

Paths are resolved relative to:

  1. Current page's directory - If you're incontent/docs/content/,snippets/warning.mdlooks incontent/docs/content/snippets/
  2. Site root - Falls back to site root if not found relative to page

Example: Path Resolution

  • Page:content/docs/getting-started/installation.md
  • Include:snippets/warning.md
  • Resolves to:content/docs/getting-started/snippets/warning.md(orcontent/snippets/warning.mdif not found)

Examples

Include Entire File:

1
2
:::{include} snippets/warning.md
:::

Include Specific Lines:

1
2
3
4
:::{include} snippets/api-example.md
:start-line: 5
:end-line: 20
:::

Nested Directives: Included content can use other directives:

1
2
3
4
<!-- snippets/warning.md -->
:::{warning}
This feature is in beta.
:::

Literal Include

Include code files as syntax-highlighted code blocks.

Syntax:

1
2
:::{literalinclude} path/to/file.py
:::

With Options:

1
2
3
4
5
6
7
:::{literalinclude} path/to/file.py
:language: python
:start-line: 10
:end-line: 25
:emphasize-lines: 15,16,17
:linenos: true
:::

Options:

  • :language:- Override auto-detected language
  • :start-line:- Starting line number (1-indexed)
  • :end-line:- Ending line number (1-indexed)
  • :emphasize-lines:- Highlight specific lines:7,8,9or7-9
  • :linenos:- Show line numbers:true,false(default:false)

Language Detection

literalincludeauto-detects language from file extensions:

  • Python:.py
  • JavaScript:.js,.ts
  • Web:.html,.css
  • Config:.yaml,.yml,.json,.toml
  • Shell:.sh,.bash,.zsh
  • And many more

Examples

Basic Include:

1
2
:::{literalinclude} examples/api.py
:::

With Line Range:

1
2
3
4
:::{literalinclude} examples/api.py
:start-line: 10
:end-line: 25
:::

With Emphasized Lines:

1
2
3
:::{literalinclude} examples/api.py
:emphasize-lines: 7,8,9
:::

With Line Numbers:

1
2
3
:::{literalinclude} examples/api.py
:linenos: true
:::

Complete Example:

1
2
3
4
5
6
7
:::{literalinclude} examples/api.py
:language: python
:start-line: 10
:end-line: 30
:emphasize-lines: 15,16,17
:linenos: true
:::

Path Resolution

Same as{include}- paths resolve relative to current page's directory, then site root.

Security

Both directives prevent path traversal attacks:

  • Only allows paths within the site root
  • Rejects paths with..sequences
  • Validates file existence before inclusion

Best Practices

Organize Snippets

Create a dedicated directory structure:

content/
├── snippets/
│   ├── warnings/
│   │   ├── beta-notice.md
│   │   └── deprecated-feature.md
│   ├── code-examples/
│   │   ├── api-client.py
│   │   └── config.yaml
│   └── common-content/
│       ├── installation-steps.md
│       └── troubleshooting.md
└── docs/
    └── guides/
        └── my-guide.md  # Uses snippets via {include}

Keep Snippets Focused

Each snippet should have a single purpose:

Good:snippets/warnings/beta-notice.md- One warning
Bad:snippets/all-warnings.md- Multiple warnings mixed together

Use Relative Paths

Prefer relative paths for portability:

Good:snippets/warning.md
Bad:/absolute/path/to/warning.md

Document Snippets

Add comments explaining purpose:

1
2
3
4
5
6
7
8
9
<!--
Purpose: Beta feature warning
Used in: Installation guides, API docs
Last updated: 2025-01-15
-->

:::{warning}
This feature is in beta.
:::

Common Patterns

Reusable Warnings

1
2
3
4
<!-- snippets/warnings/beta.md -->
:::{warning}
This feature is in beta. Please report issues.
:::

Use in multiple pages:

1
2
:::{include} snippets/warnings/beta.md
:::

Code Examples

1
2
3
4
<!-- snippets/code/api-example.py -->
def get_user(user_id: int) -> User:
    """Get user by ID."""
    return db.query(User).filter(User.id == user_id).first()

Include with emphasis:

1
2
3
:::{literalinclude} snippets/code/api-example.py
:emphasize-lines: 2
:::

Troubleshooting