0
# Macros and Extensions
1
2
Built-in macros for extended functionality and utilities for creating custom macros. python-creole supports macro expansion within Creole markup, enabling syntax highlighting, raw HTML inclusion, and custom processing functions.
3
4
## Capabilities
5
6
### Built-in Macros
7
8
Pre-defined macro functions for common extended markup needs.
9
10
```python { .api }
11
def html(text: str) -> str: ...
12
def pre(text: str) -> str: ...
13
def code(ext: str, text: str) -> str: ...
14
```
15
16
**Usage Examples:**
17
18
```python
19
from creole.shared.example_macros import html, pre, code
20
from creole import creole2html
21
22
# HTML pass-through macro
23
macros = {'html': html}
24
markup = '<<html>><div class="custom">Custom HTML</div><</html>>'
25
result = creole2html(markup, macros=macros)
26
# Returns: '<div class="custom">Custom HTML</div>'
27
28
# Preformatted text macro
29
macros = {'pre': pre}
30
markup = '<<pre>>Code with spaces\nand newlines<</pre>>'
31
result = creole2html(markup, macros=macros)
32
# Returns: '<pre>Code with spaces\nand newlines</pre>'
33
34
# Syntax highlighting macro (requires pygments)
35
macros = {'code': code}
36
markup = '''<<code ext="python">>
37
def hello():
38
print("Hello, world!")
39
<</code>>'''
40
result = creole2html(markup, macros=macros)
41
# Returns syntax-highlighted HTML if pygments is available
42
```
43
44
### HTML Pass-through Macro
45
46
Allow raw HTML content within Creole markup.
47
48
```python { .api }
49
def html(text: str) -> str
50
```
51
52
**Parameters:**
53
- `text`: Raw HTML content to pass through unchanged
54
55
**Returns:** HTML string (unchanged input)
56
57
**Usage Examples:**
58
59
```python
60
from creole.shared.example_macros import html
61
62
# Direct usage
63
output = html('<div class="highlight">Special content</div>')
64
# Returns: '<div class="highlight">Special content</div>'
65
66
# In Creole markup
67
creole_markup = '''
68
Normal paragraph.
69
70
<<html>>
71
<div class="custom-widget">
72
<p>Custom HTML widget</p>
73
<button onclick="alert('Hi!')">Click me</button>
74
</div>
75
<</html>>
76
77
Another paragraph.
78
'''
79
```
80
81
### Preformatted Text Macro
82
83
Wrap text in HTML pre tags with proper escaping.
84
85
```python { .api }
86
def pre(text: str) -> str
87
```
88
89
**Parameters:**
90
- `text`: Text content to wrap in pre tags
91
92
**Returns:** HTML pre element with escaped content
93
94
**Usage Examples:**
95
96
```python
97
from creole.shared.example_macros import pre
98
99
# Direct usage
100
output = pre('Code with <special> characters & symbols')
101
# Returns: '<pre>Code with <special> characters & symbols</pre>'
102
103
# In Creole markup
104
creole_markup = '''
105
Here's some code:
106
107
<<pre>>
108
function example() {
109
return "Hello <world>";
110
}
111
<</pre>>
112
'''
113
```
114
115
### Syntax Highlighting Macro
116
117
Syntax highlight code using Pygments if available, otherwise fall back to preformatted text.
118
119
```python { .api }
120
def code(ext: str, text: str) -> str
121
```
122
123
**Parameters:**
124
- `ext`: File extension or language identifier (e.g., "python", ".py", "js", ".css")
125
- `text`: Source code to highlight
126
127
**Returns:** HTML with syntax highlighting or preformatted text fallback
128
129
**Usage Examples:**
130
131
```python
132
from creole.shared.example_macros import code
133
134
# Direct usage
135
python_code = '''
136
def factorial(n):
137
if n <= 1:
138
return 1
139
return n * factorial(n - 1)
140
'''
141
output = code("python", python_code)
142
# Returns syntax-highlighted HTML if pygments available
143
144
# Different language identifiers
145
js_output = code("js", "console.log('Hello world!');")
146
css_output = code(".css", "body { margin: 0; }")
147
generic_output = code("text", "Plain text content")
148
149
# In Creole markup
150
creole_markup = '''
151
Python example:
152
153
<<code ext="python">>
154
import sys
155
print(f"Python version: {sys.version}")
156
<</code>>
157
158
JavaScript example:
159
160
<<code ext=".js">>
161
const message = "Hello, world!";
162
document.body.innerHTML = message;
163
<</code>>
164
'''
165
```
166
167
## Utility Functions
168
169
### Pygments Integration
170
171
Helper functions for syntax highlighting integration.
172
173
```python { .api }
174
def get_pygments_lexer(source_type: str, code: str): ...
175
def get_pygments_formatter(): ...
176
```
177
178
**Usage Examples:**
179
180
```python
181
from creole.shared.utils import get_pygments_lexer, get_pygments_formatter
182
183
# Get lexer for specific language
184
lexer = get_pygments_lexer("python", "print('hello')")
185
formatter = get_pygments_formatter()
186
187
# Check if pygments is available
188
try:
189
from pygments import highlight
190
highlighted = highlight(code, lexer, formatter)
191
except ImportError:
192
highlighted = f"<pre>{code}</pre>" # Fallback
193
```
194
195
### String Processing Utilities
196
197
Utilities for macro parameter processing.
198
199
```python { .api }
200
def string2dict(raw_content: str) -> dict: ...
201
def dict2string(d: dict) -> str: ...
202
```
203
204
**Usage Examples:**
205
206
```python
207
from creole.shared.utils import string2dict, dict2string
208
209
# Parse macro parameters
210
params = string2dict('key1="value1" key2=42 key3=true')
211
# Returns: {'key1': 'value1', 'key2': 42, 'key3': True}
212
213
# Convert back to string
214
param_string = dict2string({'lang': 'python', 'line_numbers': True})
215
# Returns: 'lang="python" line_numbers=True'
216
```
217
218
## Creating Custom Macros
219
220
### Simple Macro Functions
221
222
Macros are Python functions that take text input and return HTML output.
223
224
```python
225
# Simple macro that wraps text in a div
226
def highlight_macro(text):
227
return f'<div class="highlight">{text}</div>'
228
229
# Macro with parameters using string2dict
230
def box_macro(params, text):
231
from creole.shared.utils import string2dict
232
options = string2dict(params)
233
css_class = options.get('class', 'box')
234
color = options.get('color', 'blue')
235
return f'<div class="{css_class}" style="border-color: {color};">{text}</div>'
236
237
# Usage in creole2html
238
macros = {
239
'highlight': highlight_macro,
240
'box': box_macro
241
}
242
243
markup = '''
244
<<highlight>>Important text<</highlight>>
245
246
<<box class="info" color="green">>
247
This is an info box.
248
<</box>>
249
'''
250
251
html = creole2html(markup, macros=macros)
252
```
253
254
### Advanced Macro Patterns
255
256
```python
257
# Macro with file inclusion
258
def include_macro(filename):
259
try:
260
with open(filename, 'r', encoding='utf-8') as f:
261
content = f.read()
262
return f'<pre><code>{content}</code></pre>'
263
except FileNotFoundError:
264
return f'<p class="error">File not found: {filename}</p>'
265
266
# Macro with markdown processing
267
def markdown_macro(text):
268
try:
269
import markdown
270
return markdown.markdown(text)
271
except ImportError:
272
return f'<pre>{text}</pre>' # Fallback
273
274
# Conditional macro
275
def platform_macro(platform, text):
276
import sys
277
if sys.platform.startswith(platform):
278
return text
279
return '' # Hide content on other platforms
280
281
macros = {
282
'include': include_macro,
283
'markdown': markdown_macro,
284
'platform': platform_macro
285
}
286
```
287
288
## Macro Error Handling
289
290
Macros should handle errors gracefully and provide fallback behavior:
291
292
```python
293
def safe_macro(text):
294
try:
295
# Risky operation
296
result = complex_processing(text)
297
return result
298
except Exception as e:
299
# Log error and provide fallback
300
import sys
301
print(f"Macro error: {e}", file=sys.stderr)
302
return f'<pre>{text}</pre>' # Safe fallback
303
```
304
305
## Testing Macros
306
307
```python
308
from creole import creole2html
309
310
def test_macro():
311
def test_macro_func(text):
312
return f'<span class="test">{text}</span>'
313
314
macros = {'test': test_macro_func}
315
result = creole2html('<<test>>content<</test>>', macros=macros)
316
expected = '<span class="test">content</span>'
317
assert expected in result
318
319
test_macro()
320
```