0
# Link and Reference Extras
1
2
Extensions for advanced link processing, auto-linking, reference management, and URL handling that enhance markdown's linking capabilities.
3
4
## Capabilities
5
6
### Auto-Linking Patterns
7
8
Automatically convert text patterns to clickable links using regular expressions.
9
10
```python { .api }
11
# link-patterns extra - auto-link regex patterns
12
link_patterns = [
13
(compiled_regex, replacement_string_or_callable),
14
# More patterns...
15
]
16
extras = {"link-patterns": link_patterns}
17
```
18
19
**Usage Examples:**
20
21
```python
22
import markdown2
23
import re
24
25
# Auto-link issue numbers
26
issue_pattern = (
27
re.compile(r'issue #(\d+)'),
28
r'https://github.com/user/repo/issues/\1'
29
)
30
31
# Auto-link user mentions
32
user_pattern = (
33
re.compile(r'@(\w+)'),
34
lambda m: f'<a href="/users/{m.group(1)}">@{m.group(1)}</a>'
35
)
36
37
# Auto-link bug numbers
38
bug_pattern = (
39
re.compile(r'bug (\d+)'),
40
r'<a href="http://bugs.example.com/\1">bug \1</a>'
41
)
42
43
text = "See issue #123 and @john for bug 456 details"
44
html = markdown2.markdown(
45
text,
46
extras={"link-patterns": [issue_pattern, user_pattern, bug_pattern]}
47
)
48
```
49
50
### Reference Link Shortcuts
51
52
Simplified reference link syntax and shortcut handling.
53
54
```python { .api }
55
# link-shortrefs extra - allow shortcut reference links without []
56
extras = ["link-shortrefs"]
57
```
58
59
**Usage Examples:**
60
61
```python
62
import markdown2
63
64
markdown_text = '''
65
Visit [Google] or [Python].
66
67
[Google]: https://google.com
68
[Python]: https://python.org
69
'''
70
71
# Standard markdown requires [Google][] syntax
72
# With link-shortrefs, [Google] works directly
73
html = markdown2.markdown(markdown_text, extras=["link-shortrefs"])
74
```
75
76
### File Link Processing
77
78
Convert markdown file links to HTML file links automatically.
79
80
```python { .api }
81
# markdown-file-links extra - convert .md links to .html
82
extras = ["markdown-file-links"]
83
84
# With configuration options
85
extras = {
86
"markdown-file-links": {
87
"url_rewrite_func": custom_rewrite_function
88
}
89
}
90
```
91
92
**Usage Examples:**
93
94
```python
95
import markdown2
96
97
markdown_text = '''
98
See the [installation guide](install.md) and [API docs](api/reference.md) for details.
99
'''
100
101
html = markdown2.markdown(markdown_text, extras=["markdown-file-links"])
102
# Converts install.md -> install.html
103
# Converts api/reference.md -> api/reference.html
104
105
# Custom URL rewriting
106
def custom_rewrite(url):
107
if url.endswith('.md'):
108
return url.replace('.md', '.html')
109
return url
110
111
html = markdown2.markdown(
112
markdown_text,
113
extras={"markdown-file-links": {"url_rewrite_func": custom_rewrite}}
114
)
115
```
116
117
### SEO and Security Features
118
119
Add rel="nofollow" attribute to external links for SEO and security.
120
121
```python { .api }
122
# nofollow extra - add rel="nofollow" to <a> tags with href
123
extras = ["nofollow"]
124
```
125
126
**Usage Examples:**
127
128
```python
129
import markdown2
130
131
markdown_text = '''
132
Visit [our site](https://example.com) or [external site](https://external.com).
133
'''
134
135
html = markdown2.markdown(markdown_text, extras=["nofollow"])
136
# Adds rel="nofollow" to all links with href attributes
137
```
138
139
## Advanced Link Processing
140
141
### Custom Link Pattern Functions
142
143
Create sophisticated link processing with callable replacements:
144
145
```python
146
import markdown2
147
import re
148
149
def process_ticket_links(match):
150
"""Convert ticket references to full HTML links with metadata."""
151
ticket_id = match.group(1)
152
return f'''
153
<a href="/tickets/{ticket_id}"
154
class="ticket-link"
155
data-ticket-id="{ticket_id}"
156
title="View ticket #{ticket_id}">
157
Ticket #{ticket_id}
158
</a>
159
'''
160
161
def process_user_mentions(match):
162
"""Convert @username to user profile links."""
163
username = match.group(1)
164
return f'''
165
<a href="/users/{username}"
166
class="user-mention"
167
data-username="{username}">
168
@{username}
169
</a>
170
'''
171
172
patterns = [
173
(re.compile(r'ticket #(\d+)', re.IGNORECASE), process_ticket_links),
174
(re.compile(r'@([a-zA-Z0-9_]+)'), process_user_mentions),
175
]
176
177
text = "User @alice reported ticket #1234 yesterday."
178
html = markdown2.markdown(text, extras={"link-patterns": patterns})
179
```
180
181
### Combining Link Extras
182
183
Use multiple link extras together for comprehensive link processing:
184
185
```python
186
import markdown2
187
import re
188
189
# GitHub-style link processing
190
github_patterns = [
191
# Issue references: #123
192
(re.compile(r'#(\d+)'), r'https://github.com/owner/repo/issues/\1'),
193
194
# Pull request references: PR #123
195
(re.compile(r'PR #(\d+)'), r'https://github.com/owner/repo/pull/\1'),
196
197
# Commit references: abc1234
198
(re.compile(r'\b([a-f0-9]{7,40})\b'), r'https://github.com/owner/repo/commit/\1'),
199
200
# User mentions: @username
201
(re.compile(r'@([a-zA-Z0-9-]+)'), r'https://github.com/\1'),
202
]
203
204
markdown_text = '''
205
# Project Documentation
206
207
See the [setup guide](setup.md) for installation.
208
209
Bug reported by @john in #123, fixed in commit abc1234.
210
Also see PR #456 for related changes.
211
212
External reference: [Stack Overflow](https://stackoverflow.com)
213
'''
214
215
html = markdown2.markdown(
216
markdown_text,
217
extras={
218
"link-patterns": github_patterns,
219
"markdown-file-links": None,
220
"link-shortrefs": None,
221
"nofollow": None,
222
"header-ids": None
223
}
224
)
225
```
226
227
## Configuration Options
228
229
### Link Pattern Configuration
230
231
Link patterns are specified as tuples of `(pattern, replacement)`:
232
233
```python
234
import re
235
236
# String replacement with capture groups
237
pattern1 = (re.compile(r'bug (\d+)'), r'<a href="/bugs/\1">Bug \1</a>')
238
239
# Callable replacement for complex processing
240
def custom_replacer(match):
241
return f"<custom>{match.group(0)}</custom>"
242
243
pattern2 = (re.compile(r'CUSTOM-(\w+)'), custom_replacer)
244
245
# Multiple patterns
246
patterns = [pattern1, pattern2]
247
extras = {"link-patterns": patterns}
248
```
249
250
### File Link Rewriting
251
252
Customize how markdown file links are converted:
253
254
```python
255
def custom_md_rewriter(url):
256
"""Custom function to rewrite .md URLs."""
257
if url.endswith('.md'):
258
# Convert to .html and add version parameter
259
return url.replace('.md', '.html') + '?v=latest'
260
return url
261
262
extras = {
263
"markdown-file-links": {
264
"url_rewrite_func": custom_md_rewriter
265
}
266
}
267
```
268
269
## Integration Examples
270
271
### Documentation Site Processing
272
273
```python
274
import markdown2
275
import re
276
277
# Documentation site with cross-references
278
doc_patterns = [
279
# API references: {{api:function_name}}
280
(re.compile(r'\{\{api:([^}]+)\}\}'), r'<a href="/api/\1" class="api-link">\1</a>'),
281
282
# Tutorial references: {{tutorial:name}}
283
(re.compile(r'\{\{tutorial:([^}]+)\}\}'), r'<a href="/tutorials/\1" class="tutorial-link">\1</a>'),
284
285
# External docs: {{external:name}}
286
(re.compile(r'\{\{external:([^}]+)\}\}'), r'<a href="https://docs.example.com/\1" rel="nofollow">\1</a>'),
287
]
288
289
processor = markdown2.Markdown(
290
extras={
291
"link-patterns": doc_patterns,
292
"markdown-file-links": None,
293
"header-ids": None,
294
"toc": None,
295
"tables": None
296
}
297
)
298
299
documentation_html = processor.convert(doc_content)
300
```
301
302
### External Link Behavior
303
304
Control how external links are opened by adding target attributes automatically.
305
306
```python { .api }
307
# target-blank-links extra - add target="_blank" to external links
308
extras = ["target-blank-links"]
309
```
310
311
**Usage Examples:**
312
313
```python
314
import markdown2
315
316
content = '''
317
# Links Demo
318
319
[Internal link](./local-page.md)
320
[External link](https://example.com)
321
[Another external](https://github.com/user/repo)
322
'''
323
324
html = markdown2.markdown(content, extras=["target-blank-links"])
325
# External links get target="_blank" attribute automatically
326
# Internal/relative links remain unchanged
327
```
328
329
### Blog Processing with Auto-Links
330
331
```python
332
import markdown2
333
import re
334
335
# Blog-style auto-linking
336
blog_patterns = [
337
# Tag links: #tag
338
(re.compile(r'(?<!\w)#([a-zA-Z0-9_]+)'), r'<a href="/tags/\1" class="tag-link">#\1</a>'),
339
340
# Category links: [category:name]
341
(re.compile(r'\[category:([^]]+)\]'), r'<a href="/category/\1" class="category-link">\1</a>'),
342
]
343
344
blog_processor = markdown2.Markdown(
345
extras={
346
"link-patterns": blog_patterns,
347
"nofollow": None, # Add nofollow to external links
348
"smarty-pants": None, # Nice typography
349
"break-on-newline": None # GitHub-style line breaks
350
}
351
)
352
353
blog_html = blog_processor.convert(blog_post_content)
354
```