0
# Template Environment
1
2
Core template environment providing access to variables, macros, filters, and rendering capabilities. The environment object is the primary interface for interacting with the plugin from within modules and templates.
3
4
## Capabilities
5
6
### Environment Properties
7
8
Core properties providing access to template components and configuration.
9
10
```python { .api }
11
class MacrosPlugin:
12
@property
13
def variables(self) -> dict:
14
"""Dictionary of all template variables"""
15
16
@property
17
def macros(self) -> dict:
18
"""Dictionary of all macro functions"""
19
20
@property
21
def filters(self) -> dict:
22
"""Dictionary of all filter functions"""
23
24
@property
25
def env(self) -> Environment:
26
"""Jinja2 Environment object for template rendering"""
27
28
@property
29
def conf(self) -> dict:
30
"""Complete MkDocs configuration dictionary"""
31
32
@property
33
def project_dir(self) -> str:
34
"""Project root directory path"""
35
```
36
37
#### Usage Examples
38
39
Accessing environment data:
40
```python
41
def define_env(env):
42
# Access configuration
43
site_name = env.conf.get('site_name', 'Unknown Site')
44
env.variables['site_title'] = site_name.upper()
45
46
# Check existing macros
47
if 'existing_macro' in env.macros:
48
print("Macro already exists")
49
50
# Access project directory
51
config_file = os.path.join(env.project_dir, 'config.json')
52
if os.path.exists(config_file):
53
# Load additional configuration
54
pass
55
```
56
57
### Page Context Properties
58
59
Properties available during page rendering, providing access to current page information.
60
61
```python { .api }
62
class MacrosPlugin:
63
@property
64
def page(self) -> Page:
65
"""Current page object with metadata, title, URL, etc."""
66
67
@property
68
def markdown(self) -> str:
69
"""Current page markdown content"""
70
71
@markdown.setter
72
def markdown(self, value: str):
73
"""Set current page markdown content"""
74
75
@property
76
def raw_markdown(self) -> str:
77
"""DEPRECATED: Use markdown property instead (removed in v1.1.0)"""
78
```
79
80
#### Usage Examples
81
82
Page-specific processing:
83
```python
84
def on_pre_page_macros(env):
85
"""Modify content based on page properties"""
86
87
# Add page-specific header
88
if env.page.title:
89
header = f"# {env.page.title}\\n\\n"
90
env.markdown = header + env.markdown
91
92
# Check page metadata
93
if 'api' in env.page.meta:
94
env.markdown = "!!! info\\n This is an API page\\n\\n" + env.markdown
95
96
# Access page file information
97
if env.page.file.src_path.startswith('tutorials/'):
98
env.variables['is_tutorial'] = True
99
```
100
101
### Function Registration
102
103
Methods for registering custom macros and filters that can be used in templates.
104
105
```python { .api }
106
class MacrosPlugin:
107
def macro(self, function: callable, name: str = '') -> callable:
108
"""
109
Register a function as a macro.
110
111
Args:
112
function: The function to register
113
name: Optional custom name (uses function.__name__ if not provided)
114
115
Returns:
116
The original function (allows use as decorator)
117
"""
118
119
def filter(self, function: callable, name: str = '') -> callable:
120
"""
121
Register a function as a filter.
122
123
Args:
124
function: The filter function to register
125
name: Optional custom name (uses function.__name__ if not provided)
126
127
Returns:
128
The original function (allows use as decorator)
129
"""
130
```
131
132
#### Usage Examples
133
134
Decorator registration:
135
```python
136
def define_env(env):
137
@env.macro
138
def current_year():
139
"""Get current year"""
140
return datetime.now().year
141
142
@env.filter
143
def slugify(text):
144
"""Convert text to URL-friendly slug"""
145
return re.sub(r'[^\w\s-]', '', text).strip().lower()
146
147
@env.macro
148
def button(text, url, style='primary'):
149
"""Generate HTML button"""
150
return f'<a class="btn btn-{style}" href="{url}">{text}</a>'
151
```
152
153
Direct registration:
154
```python
155
def define_env(env):
156
def price_calculator(base_price, tax_rate=0.1):
157
return base_price * (1 + tax_rate)
158
159
def format_currency(amount, symbol='$'):
160
return f"{symbol}{amount:.2f}"
161
162
# Register with custom names
163
env.macro(price_calculator, 'calc_price')
164
env.filter(format_currency, 'currency')
165
```
166
167
### Template Rendering
168
169
Methods for rendering markdown content and checking for template syntax.
170
171
```python { .api }
172
class MacrosPlugin:
173
def render(self, markdown: str, force_rendering: bool = False) -> str:
174
"""
175
Render markdown content with Jinja2 templates.
176
177
Args:
178
markdown: The markdown content to render
179
force_rendering: Force rendering even if page metadata says not to
180
181
Returns:
182
Rendered markdown content
183
"""
184
185
def has_j2(self, s: str) -> bool:
186
"""
187
Check if string contains Jinja2 template syntax.
188
189
Args:
190
s: String to check
191
192
Returns:
193
True if string contains Jinja2 markers
194
"""
195
```
196
197
#### Usage Examples
198
199
Custom rendering:
200
```python
201
def define_env(env):
202
@env.macro
203
def render_template(template_name):
204
"""Render external template file"""
205
template_path = os.path.join(env.project_dir, 'templates', template_name)
206
if os.path.exists(template_path):
207
with open(template_path, 'r') as f:
208
content = f.read()
209
return env.render(content, force_rendering=True)
210
return f"Template not found: {template_name}"
211
212
@env.macro
213
def conditional_content(content):
214
"""Only render if content has templates"""
215
if env.has_j2(content):
216
return env.render(content)
217
return content
218
```
219
220
### Hook Functions Access
221
222
Properties providing access to registered hook functions for advanced use cases.
223
224
```python { .api }
225
class MacrosPlugin:
226
@property
227
def pre_macro_functions(self) -> list:
228
"""List of pre-macro processing functions"""
229
230
@property
231
def post_macro_functions(self) -> list:
232
"""List of post-macro processing functions"""
233
234
@property
235
def post_build_functions(self) -> list:
236
"""List of post-build processing functions"""
237
```
238
239
### Path and File Utilities
240
241
Methods for working with file paths and determining rendering behavior.
242
243
```python { .api }
244
class MacrosPlugin:
245
def force_page_rendering(self, filename: str) -> bool:
246
"""
247
Check if page should be force-rendered based on configuration.
248
249
Args:
250
filename: Page filename relative to docs directory
251
252
Returns:
253
True if page matches force_render_paths patterns
254
"""
255
```
256
257
#### Usage Examples
258
259
Path-based logic:
260
```python
261
def on_pre_page_macros(env):
262
"""Apply different processing based on file path"""
263
264
current_file = env.page.file.src_path
265
266
# Check if forced rendering
267
if env.force_page_rendering(current_file):
268
env.variables['force_rendered'] = True
269
270
# Apply different templates based on path
271
if current_file.startswith('api/'):
272
env.markdown = "{% include 'api_template.md' %}\\n" + env.markdown
273
elif current_file.startswith('tutorials/'):
274
env.markdown = "{% include 'tutorial_template.md' %}\\n" + env.markdown
275
```
276
277
## Environment Object Structure
278
279
The environment object passed to module functions provides access to:
280
281
```python
282
env.variables # Template variables dictionary
283
env.macros # Macro functions dictionary
284
env.filters # Filter functions dictionary
285
env.conf # Complete MkDocs configuration
286
env.env # Jinja2 Environment object
287
env.project_dir # Project root directory
288
env.page # Current page (during rendering)
289
env.markdown # Current page content (during rendering)
290
```
291
292
## Template Access Patterns
293
294
Variables and functions registered in the environment become available in templates:
295
296
```markdown
297
<!-- Variables -->
298
{{ my_variable }}
299
{{ config.site_name }}
300
301
<!-- Macros -->
302
{{ my_macro("argument") }}
303
{{ button("Click Me", "/page") }}
304
305
<!-- Filters -->
306
{{ "text" | my_filter }}
307
{{ page.title | slugify }}
308
309
<!-- Combined -->
310
{{ button(page.title | slugify, page.url) }}
311
```