or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

built-in-context.mdbuilt-in-functions.mdexternal-integration.mdindex.mdmodule-system.mdplugin-configuration.mdtemplate-environment.md

external-integration.mddocs/

0

# External Integration

1

2

Methods for integrating with other MkDocs plugins and external systems, including registration hooks and debugging utilities.

3

4

## Capabilities

5

6

### Plugin Registration Hooks

7

8

Methods for other MkDocs plugins to register macros, filters, and variables with the macros plugin.

9

10

```python { .api }

11

class MacrosPlugin:

12

def register_macros(self, items: dict):

13

"""

14

Register macros from external plugins.

15

16

Args:

17

items: Dictionary of {name: function} pairs

18

19

Raises:

20

KeyError: If macro name already exists

21

"""

22

23

def register_filters(self, items: dict):

24

"""

25

Register filters from external plugins.

26

27

Args:

28

items: Dictionary of {name: function} pairs

29

30

Raises:

31

KeyError: If filter name already exists

32

"""

33

34

def register_variables(self, items: dict):

35

"""

36

Register variables from external plugins.

37

38

Args:

39

items: Dictionary of {name: value} pairs

40

41

Raises:

42

KeyError: If variable name already exists

43

"""

44

```

45

46

#### Usage Examples

47

48

From another MkDocs plugin:

49

```python

50

class MyPlugin(BasePlugin):

51

def on_config(self, config):

52

# Find the macros plugin

53

for plugin in config.plugins:

54

if hasattr(plugin, 'register_macros'):

55

# Register our functions

56

plugin.register_macros({

57

'my_custom_macro': self.my_macro_function,

58

'another_macro': lambda x: f"Processed: {x}"

59

})

60

61

plugin.register_filters({

62

'my_filter': self.my_filter_function

63

})

64

65

plugin.register_variables({

66

'plugin_version': '1.0.0',

67

'plugin_config': self.config

68

})

69

break

70

71

def my_macro_function(self, text):

72

return f"<span class='highlight'>{text}</span>"

73

74

def my_filter_function(self, value):

75

return str(value).replace(' ', '_')

76

```

77

78

Standalone registration utility:

79

```python

80

def register_with_macros(config, macros_dict, filters_dict=None, variables_dict=None):

81

"""Utility to register items with macros plugin"""

82

for plugin in config.plugins:

83

if hasattr(plugin, 'register_macros'):

84

if macros_dict:

85

plugin.register_macros(macros_dict)

86

if filters_dict:

87

plugin.register_filters(filters_dict)

88

if variables_dict:

89

plugin.register_variables(variables_dict)

90

return True

91

return False

92

```

93

94

### Debug and Logging Utilities

95

96

Methods for creating debug output and logging functionality within macros.

97

98

```python { .api }

99

class MacrosPlugin:

100

def start_chatting(self, prefix: str, color: str = 'yellow') -> callable:

101

"""

102

Create a debug function for verbose output.

103

104

Args:

105

prefix: Module/component name for log messages

106

color: Color for terminal output ('yellow', 'green', 'red', etc.)

107

108

Returns:

109

Chatter function that logs messages when verbose mode is enabled

110

"""

111

```

112

113

#### Usage Examples

114

115

Module with debug output:

116

```python

117

def define_env(env):

118

# Create debug function

119

chatter = env.start_chatting('MY_MODULE', 'green')

120

121

chatter("Module initialization started")

122

123

@env.macro

124

def debug_macro(value):

125

chatter(f"Processing value: {value}")

126

result = str(value).upper()

127

chatter(f"Result: {result}")

128

return result

129

130

chatter("Module loaded successfully")

131

```

132

133

Conditional debugging:

134

```python

135

def define_env(env):

136

chatter = env.start_chatting('DATA_PROCESSOR')

137

138

@env.macro

139

def process_data(data_list):

140

chatter(f"Processing {len(data_list)} items")

141

142

results = []

143

for i, item in enumerate(data_list):

144

chatter(f"Processing item {i}: {item}")

145

processed = item.upper().strip()

146

results.append(processed)

147

148

chatter(f"Completed processing, {len(results)} results")

149

return results

150

```

151

152

Multi-level debugging:

153

```python

154

def define_env(env):

155

# Different debug levels with colors

156

info = env.start_chatting('INFO', 'blue')

157

warn = env.start_chatting('WARN', 'yellow')

158

error = env.start_chatting('ERROR', 'red')

159

160

@env.macro

161

def safe_operation(value):

162

info("Starting safe operation")

163

164

if not value:

165

warn("Empty value provided")

166

return "N/A"

167

168

try:

169

result = complex_processing(value)

170

info(f"Operation successful: {result}")

171

return result

172

except Exception as e:

173

error(f"Operation failed: {e}")

174

return "Error"

175

```

176

177

### Path and File Utilities

178

179

Methods for working with file paths and determining rendering behavior.

180

181

```python { .api }

182

class MacrosPlugin:

183

def force_page_rendering(self, filename: str) -> bool:

184

"""

185

Check if page should be force-rendered based on configuration.

186

187

Args:

188

filename: Page filename relative to docs directory

189

190

Returns:

191

True if page matches force_render_paths patterns

192

"""

193

```

194

195

#### Usage Examples

196

197

Conditional processing in hooks:

198

```python

199

def on_pre_page_macros(env):

200

"""Apply different processing based on file patterns"""

201

202

current_file = env.page.file.src_path

203

204

# Check force rendering patterns

205

if env.force_page_rendering(current_file):

206

env.variables['force_rendered'] = True

207

# Apply special processing for forced files

208

env.markdown = "<!-- Force rendered -->\n" + env.markdown

209

210

# Different processing for different file types

211

if current_file.endswith('.api.md'):

212

env.variables['is_api_doc'] = True

213

elif current_file.startswith('examples/'):

214

env.variables['is_example'] = True

215

```

216

217

File-based configuration:

218

```python

219

def define_env(env):

220

@env.macro

221

def include_if_forced(filename, content):

222

"""Only include content if file would be force-rendered"""

223

if env.force_page_rendering(filename):

224

return content

225

return ""

226

227

@env.macro

228

def get_render_status(filename):

229

"""Get rendering status for debugging"""

230

if env.force_page_rendering(filename):

231

return "Force rendered"

232

elif env.config['render_by_default']:

233

return "Default rendered"

234

else:

235

return "Opt-in only"

236

```

237

238

## Integration Patterns

239

240

### Plugin Communication

241

242

```python

243

# In another plugin

244

class MyPlugin(BasePlugin):

245

def on_config(self, config):

246

# Store reference to macros plugin

247

self.macros_plugin = None

248

for plugin in config.plugins:

249

if hasattr(plugin, 'register_macros'):

250

self.macros_plugin = plugin

251

break

252

253

def on_page_markdown(self, markdown, page, config, files):

254

# Use macros plugin for rendering

255

if self.macros_plugin:

256

# Add custom variables for this page

257

self.macros_plugin.register_variables({

258

'current_plugin': 'MyPlugin',

259

'processing_time': datetime.now()

260

})

261

```

262

263

### Shared Functionality

264

265

```python

266

# Shared utility functions for multiple plugins

267

def create_shared_macros():

268

"""Create macros that multiple plugins can use"""

269

270

def format_code(code, language='python'):

271

return f"```{language}\n{code}\n```"

272

273

def create_alert(message, type='info'):

274

return f"!!! {type}\n {message}"

275

276

def embed_youtube(video_id):

277

return f'<iframe src="https://youtube.com/embed/{video_id}"></iframe>'

278

279

return {

280

'format_code': format_code,

281

'alert': create_alert,

282

'youtube': embed_youtube

283

}

284

285

# Register from multiple plugins

286

def register_shared_functionality(config):

287

shared_macros = create_shared_macros()

288

289

for plugin in config.plugins:

290

if hasattr(plugin, 'register_macros'):

291

plugin.register_macros(shared_macros)

292

break

293

```

294

295

### Configuration Integration

296

297

```python

298

class IntegratedPlugin(BasePlugin):

299

config_scheme = (

300

('enable_macros', Type(bool, default=True)),

301

('macro_prefix', Type(str, default='plugin')),

302

)

303

304

def on_config(self, config):

305

if not self.config['enable_macros']:

306

return

307

308

# Find and configure macros plugin

309

for plugin in config.plugins:

310

if hasattr(plugin, 'register_macros'):

311

prefix = self.config['macro_prefix']

312

313

plugin.register_macros({

314

f'{prefix}_function': self.my_function,

315

f'{prefix}_utility': self.utility_function

316

})

317

318

plugin.register_variables({

319

f'{prefix}_config': dict(self.config),

320

f'{prefix}_enabled': True

321

})

322

break

323

```

324

325

## Error Handling

326

327

### Registration Conflicts

328

329

```python

330

def safe_register_macros(plugin, macros_dict):

331

"""Safely register macros with conflict handling"""

332

for name, func in macros_dict.items():

333

try:

334

plugin.register_macros({name: func})

335

except KeyError as e:

336

print(f"Warning: Macro {name} already exists: {e}")

337

# Try with prefixed name

338

prefixed_name = f"ext_{name}"

339

try:

340

plugin.register_macros({prefixed_name: func})

341

print(f"Registered as {prefixed_name} instead")

342

except KeyError:

343

print(f"Could not register {name} even with prefix")

344

```

345

346

### Plugin Detection

347

348

```python

349

def find_macros_plugin(config):

350

"""Find macros plugin in configuration"""

351

for plugin in config.plugins:

352

if hasattr(plugin, 'register_macros'):

353

return plugin

354

return None

355

356

def ensure_macros_plugin(config):

357

"""Ensure macros plugin is available"""

358

plugin = find_macros_plugin(config)

359

if not plugin:

360

raise RuntimeError("MkDocs Macros plugin not found in configuration")

361

return plugin

362

```

363

364

## Best Practices

365

366

1. **Check plugin availability** before attempting registration

367

2. **Handle registration conflicts** gracefully with prefixes or warnings

368

3. **Use descriptive prefixes** for external functions to avoid naming conflicts

369

4. **Document integration requirements** in your plugin documentation

370

5. **Test with different plugin load orders** to ensure compatibility

371

6. **Use debug output** to track registration and execution

372

7. **Provide fallbacks** when macros plugin is not available