A MkDocs plugin that injects the mkdocs.yml extra variables into the markdown template
npx @tessl/cli install tessl/pypi-mkdocs-markdownextradata-plugin@0.2.00
# MkDocs Markdown Extra Data Plugin
1
2
A MkDocs plugin that enables injection of configuration variables and external data files directly into markdown templates during site generation. It allows users to define variables in mkdocs.yml or external YAML/JSON files and reference them in markdown content using Jinja2 template syntax.
3
4
## Package Information
5
6
- **Package Name**: mkdocs-markdownextradata-plugin
7
- **Package Type**: pypi
8
- **Language**: Python
9
- **Installation**: `pip install mkdocs-markdownextradata-plugin`
10
- **Requirements**: Python 3.6+, mkdocs, pyyaml
11
12
## Core Imports
13
14
```python
15
# Plugin is automatically loaded by MkDocs when configured
16
# No direct imports needed for basic usage
17
# Plugin is registered as entry point: 'markdownextradata = markdownextradata.plugin:MarkdownExtraDataPlugin'
18
```
19
20
## Basic Usage
21
22
Configure the plugin in your `mkdocs.yml`:
23
24
```yaml
25
plugins:
26
- search
27
- markdownextradata
28
```
29
30
Define variables in `mkdocs.yml`:
31
32
```yaml
33
extra:
34
customer:
35
name: "Your Company"
36
web: "www.example.com"
37
version: "1.0.0"
38
```
39
40
Use variables in markdown files:
41
42
```markdown
43
# Welcome to {{ customer.name }}
44
45
Visit us at: {{ customer.web }}
46
Current version: {{ customer.version }}
47
```
48
49
## Capabilities
50
51
### Plugin Configuration
52
53
Configure the plugin with custom data sources and Jinja2 options.
54
55
```python { .api }
56
class MarkdownExtraDataPlugin(BasePlugin):
57
"""
58
MkDocs plugin for injecting extra variables into markdown templates.
59
60
Configuration Schema:
61
- data: Optional[str] - Data source folders (comma-separated paths)
62
- jinja_options: Optional[Dict] - Jinja2 template engine configuration
63
"""
64
65
config_scheme = (
66
("data", mkdocs.config.config_options.Type(str_type, default=None)),
67
("jinja_options", mkdocs.config.config_options.Type(dict, default={}))
68
)
69
70
# Python 2/3 compatibility
71
# str_type = str (Python 3+) or mkdocs.utils.string_types (Python 2)
72
```
73
74
**Configuration Examples:**
75
76
```yaml
77
# Basic configuration
78
plugins:
79
- markdownextradata
80
81
# With custom data directory
82
plugins:
83
- markdownextradata:
84
data: path/to/datafiles
85
86
# With multiple data directories
87
plugins:
88
- markdownextradata:
89
data: path/to/datafiles, another/path/to/datafiles
90
91
# With custom Jinja2 options
92
plugins:
93
- markdownextradata:
94
jinja_options:
95
comment_start_string: "__CUSTOMCOMMENTSTART__"
96
variable_start_string: "<<"
97
variable_end_string: ">>"
98
```
99
100
### Data Loading and Processing
101
102
Automatically loads data from configured sources and processes external files during the pre-build phase.
103
104
```python { .api }
105
def on_pre_build(self, config, **kwargs):
106
"""
107
Load data from configured directories or default _data folders.
108
109
Args:
110
config: mkdocs configuration object
111
**kwargs: Additional keyword arguments from MkDocs
112
113
Data Processing:
114
1. Parse comma-separated data paths from 'data' config option
115
2. Convert relative paths to absolute paths based on config file location
116
3. If no data paths configured, search default locations:
117
- {config_file_dir}/_data
118
- {docs_dir}/_data
119
4. Load all .yml, .yaml, .json files recursively
120
5. Create namespaced variables based on file path structure
121
122
Supported file formats: .yml, .yaml, .json
123
Namespace mapping: File path becomes variable namespace
124
"""
125
```
126
127
**Default Data Locations:**
128
- `./docs/_data/` (relative to mkdocs.yml)
129
- `./_data/` (in project root)
130
131
**File-to-Namespace Mapping:**
132
- `_data/site.yaml` → `{{ site.variable }}`
133
- `_data/sections/captions.yaml` → `{{ sections.captions.variable }}`
134
- `_data/1_example/data.yaml` → `{{ extra['1_example']['data']['variable'] }}`
135
136
### Template Rendering
137
138
Applies Jinja2 template substitution to markdown content and page titles.
139
140
```python { .api }
141
def on_page_markdown(self, markdown, page, **kwargs):
142
"""
143
Apply template substitution to page content and title.
144
145
Args:
146
markdown: str - Raw markdown content
147
page: mkdocs.structure.pages.Page - Page object
148
149
Returns:
150
str: Processed markdown with variables substituted
151
"""
152
153
def apply_template(self, template_string):
154
"""
155
Apply Jinja2 substitution to specified string.
156
157
Args:
158
template_string: str - String containing Jinja2 template syntax
159
160
Returns:
161
str: Processed string with variables substituted
162
163
Template Context:
164
- All mkdocs config variables (site_name, site_author, etc.)
165
- All extra variables from mkdocs.yml
166
- All loaded data from external files
167
168
Raises:
169
jinja2.exceptions.TemplateSyntaxError: When template syntax is invalid.
170
Displays helpful error message suggesting use of 'extra' dictionary
171
for non-Python-compliant variable names.
172
"""
173
```
174
175
### Configuration Initialization
176
177
Initializes the Jinja2 environment with custom options and prepares the MkDocs configuration.
178
179
```python { .api }
180
def on_config(self, mkdocsConfig, **kwargs):
181
"""
182
Initialize Jinja2 environment and store MkDocs configuration.
183
184
Args:
185
mkdocsConfig: mkdocs.config.Config - MkDocs configuration object
186
187
Sets up:
188
- Jinja2.Environment with DebugUndefined and custom options
189
- Access to mkdocs config and extra variables
190
"""
191
```
192
193
## Variable Access Patterns
194
195
### Direct Access
196
197
Variables defined in `mkdocs.yml` extra section:
198
199
```yaml
200
extra:
201
site_name: "My Site"
202
author: "John Doe"
203
```
204
205
```markdown
206
Site: {{ site_name }}
207
Author: {{ author }}
208
```
209
210
### Namespaced Access
211
212
External data files create namespaced variables:
213
214
```yaml
215
# _data/company/info.yaml
216
name: "ACME Corp"
217
founded: 2020
218
```
219
220
```markdown
221
Company: {{ company.info.name }}
222
Founded: {{ company.info.founded }}
223
```
224
225
### Dictionary Access
226
227
For non-Python-compliant names or safe access:
228
229
```markdown
230
<!-- For files/folders starting with numbers or containing special characters -->
231
Value: {{ extra['1_example']['data']['key'] }}
232
233
<!-- Alternative access for any variable -->
234
Site: {{ extra['site_name'] }}
235
```
236
237
## Error Handling
238
239
The plugin provides helpful error messages for common issues:
240
241
```python { .api }
242
# Template syntax errors with guidance
243
jinja2.exceptions.TemplateSyntaxError:
244
"ERROR\t- markdownextradata - One or more yaml files might not comply with "
245
"Python's variable naming conventions. Try accessing the variable through the "
246
"'extra' dictionary. Check the README for more information."
247
```
248
249
**Common Error Scenarios:**
250
- Invalid YAML/JSON syntax in data files
251
- Non-Python-compliant variable names (use dictionary access)
252
- Missing data files or directories (silently ignored)
253
- Jinja2 template syntax errors in markdown
254
255
## Data File Formats
256
257
### YAML Files (.yml, .yaml)
258
259
```yaml
260
# _data/config.yaml
261
api:
262
base_url: "https://api.example.com"
263
version: "v1"
264
endpoints:
265
users: "/users"
266
posts: "/posts"
267
```
268
269
Usage: `{{ config.api.base_url }}`
270
271
### JSON Files (.json)
272
273
```json
274
// _data/settings.json
275
{
276
"theme": {
277
"colors": {
278
"primary": "#007acc",
279
"secondary": "#f0f0f0"
280
},
281
"fonts": ["Arial", "Helvetica"]
282
}
283
}
284
```
285
286
Usage: `{{ settings.theme.colors.primary }}`
287
288
## Advanced Configuration
289
290
### Custom Jinja2 Options
291
292
Configure Jinja2 template engine delimiters and behavior:
293
294
```yaml
295
plugins:
296
- markdownextradata:
297
jinja_options:
298
# Comment delimiters
299
comment_start_string: "/*"
300
comment_end_string: "*/"
301
# Variable delimiters
302
variable_start_string: "[["
303
variable_end_string: "]]"
304
# Block delimiters
305
block_start_string: "{%"
306
block_end_string: "%}"
307
# Undefined behavior
308
undefined: "jinja2.StrictUndefined"
309
```
310
311
### Multiple Data Sources
312
313
Organize data across multiple directories:
314
315
```yaml
316
plugins:
317
- markdownextradata:
318
data: "shared/_data, project/_data, client/_data"
319
```
320
321
**Processing Order:**
322
1. Comma-separated paths are converted to absolute paths relative to mkdocs.yml location
323
2. Each directory is processed recursively using pathlib.Path.glob("**/*.{yaml,yml,json}")
324
3. File namespace derived from relative path: `os.path.splitext(os.path.relpath(filename, ds_folder))[0]`
325
4. Data added to config under ["extra"] + namespace.split(os.sep) hierarchy
326
5. Later paths can override earlier paths for same namespace
327
328
## Types
329
330
```python { .api }
331
# Python version compatibility
332
import sys
333
if sys.version_info[0] >= 3:
334
str_type = str
335
else:
336
str_type = mkdocs.utils.string_types
337
338
# Configuration constants
339
CONFIG_KEYS = [
340
"site_name",
341
"site_author",
342
"site_url",
343
"repo_url",
344
"repo_name"
345
]
346
347
# Plugin class with configuration
348
class MarkdownExtraDataPlugin(BasePlugin):
349
"""MkDocs plugin for injecting extra variables into markdown templates."""
350
351
JINJA_OPTIONS = "jinja_options"
352
353
config_scheme = (
354
("data", mkdocs.config.config_options.Type(str_type, default=None)),
355
(JINJA_OPTIONS, mkdocs.config.config_options.Type(dict, default={}))
356
)
357
358
# Instance attributes set during plugin lifecycle
359
env: jinja2.Environment # Set in on_config
360
mkdocsConfig: mkdocs.config.Config # Set in on_config
361
```