CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-markdown2

A fast and complete Python implementation of Markdown with extensive extras support

Pending
Overview
Eval results
Files

link-reference-extras.mddocs/

Link and Reference Extras

Extensions for advanced link processing, auto-linking, reference management, and URL handling that enhance markdown's linking capabilities.

Capabilities

Auto-Linking Patterns

Automatically convert text patterns to clickable links using regular expressions.

# link-patterns extra - auto-link regex patterns
link_patterns = [
    (compiled_regex, replacement_string_or_callable),
    # More patterns...
]
extras = {"link-patterns": link_patterns}

Usage Examples:

import markdown2
import re

# Auto-link issue numbers
issue_pattern = (
    re.compile(r'issue #(\d+)'),
    r'https://github.com/user/repo/issues/\1'
)

# Auto-link user mentions  
user_pattern = (
    re.compile(r'@(\w+)'),
    lambda m: f'<a href="/users/{m.group(1)}">@{m.group(1)}</a>'
)

# Auto-link bug numbers
bug_pattern = (
    re.compile(r'bug (\d+)'),
    r'<a href="http://bugs.example.com/\1">bug \1</a>'
)

text = "See issue #123 and @john for bug 456 details"
html = markdown2.markdown(
    text,
    extras={"link-patterns": [issue_pattern, user_pattern, bug_pattern]}
)

Reference Link Shortcuts

Simplified reference link syntax and shortcut handling.

# link-shortrefs extra - allow shortcut reference links without []
extras = ["link-shortrefs"]

Usage Examples:

import markdown2

markdown_text = '''
Visit [Google] or [Python].

[Google]: https://google.com
[Python]: https://python.org
'''

# Standard markdown requires [Google][] syntax
# With link-shortrefs, [Google] works directly
html = markdown2.markdown(markdown_text, extras=["link-shortrefs"])

File Link Processing

Convert markdown file links to HTML file links automatically.

# markdown-file-links extra - convert .md links to .html
extras = ["markdown-file-links"]

# With configuration options
extras = {
    "markdown-file-links": {
        "url_rewrite_func": custom_rewrite_function
    }
}

Usage Examples:

import markdown2

markdown_text = '''
See the [installation guide](install.md) and [API docs](api/reference.md) for details.
'''

html = markdown2.markdown(markdown_text, extras=["markdown-file-links"])
# Converts install.md -> install.html
# Converts api/reference.md -> api/reference.html

# Custom URL rewriting
def custom_rewrite(url):
    if url.endswith('.md'):
        return url.replace('.md', '.html')
    return url

html = markdown2.markdown(
    markdown_text,
    extras={"markdown-file-links": {"url_rewrite_func": custom_rewrite}}
)

SEO and Security Features

Add rel="nofollow" attribute to external links for SEO and security.

# nofollow extra - add rel="nofollow" to <a> tags with href
extras = ["nofollow"]

Usage Examples:

import markdown2

markdown_text = '''
Visit [our site](https://example.com) or [external site](https://external.com).
'''

html = markdown2.markdown(markdown_text, extras=["nofollow"])
# Adds rel="nofollow" to all links with href attributes

Advanced Link Processing

Custom Link Pattern Functions

Create sophisticated link processing with callable replacements:

import markdown2
import re

def process_ticket_links(match):
    """Convert ticket references to full HTML links with metadata."""
    ticket_id = match.group(1)
    return f'''
    <a href="/tickets/{ticket_id}" 
       class="ticket-link" 
       data-ticket-id="{ticket_id}"
       title="View ticket #{ticket_id}">
       Ticket #{ticket_id}
    </a>
    '''

def process_user_mentions(match):
    """Convert @username to user profile links."""
    username = match.group(1)
    return f'''
    <a href="/users/{username}" 
       class="user-mention"
       data-username="{username}">
       @{username}
    </a>
    '''

patterns = [
    (re.compile(r'ticket #(\d+)', re.IGNORECASE), process_ticket_links),
    (re.compile(r'@([a-zA-Z0-9_]+)'), process_user_mentions),
]

text = "User @alice reported ticket #1234 yesterday."
html = markdown2.markdown(text, extras={"link-patterns": patterns})

Combining Link Extras

Use multiple link extras together for comprehensive link processing:

import markdown2
import re

# GitHub-style link processing
github_patterns = [
    # Issue references: #123
    (re.compile(r'#(\d+)'), r'https://github.com/owner/repo/issues/\1'),
    
    # Pull request references: PR #123  
    (re.compile(r'PR #(\d+)'), r'https://github.com/owner/repo/pull/\1'),
    
    # Commit references: abc1234
    (re.compile(r'\b([a-f0-9]{7,40})\b'), r'https://github.com/owner/repo/commit/\1'),
    
    # User mentions: @username
    (re.compile(r'@([a-zA-Z0-9-]+)'), r'https://github.com/\1'),
]

markdown_text = '''
# Project Documentation

See the [setup guide](setup.md) for installation.

Bug reported by @john in #123, fixed in commit abc1234.
Also see PR #456 for related changes.

External reference: [Stack Overflow](https://stackoverflow.com)
'''

html = markdown2.markdown(
    markdown_text,
    extras={
        "link-patterns": github_patterns,
        "markdown-file-links": None,
        "link-shortrefs": None,
        "nofollow": None,
        "header-ids": None
    }
)

Configuration Options

Link Pattern Configuration

Link patterns are specified as tuples of (pattern, replacement):

import re

# String replacement with capture groups
pattern1 = (re.compile(r'bug (\d+)'), r'<a href="/bugs/\1">Bug \1</a>')

# Callable replacement for complex processing
def custom_replacer(match):
    return f"<custom>{match.group(0)}</custom>"

pattern2 = (re.compile(r'CUSTOM-(\w+)'), custom_replacer)

# Multiple patterns
patterns = [pattern1, pattern2]
extras = {"link-patterns": patterns}

File Link Rewriting

Customize how markdown file links are converted:

def custom_md_rewriter(url):
    """Custom function to rewrite .md URLs."""
    if url.endswith('.md'):
        # Convert to .html and add version parameter
        return url.replace('.md', '.html') + '?v=latest'
    return url

extras = {
    "markdown-file-links": {
        "url_rewrite_func": custom_md_rewriter
    }
}

Integration Examples

Documentation Site Processing

import markdown2
import re

# Documentation site with cross-references
doc_patterns = [
    # API references: {{api:function_name}}
    (re.compile(r'\{\{api:([^}]+)\}\}'), r'<a href="/api/\1" class="api-link">\1</a>'),
    
    # Tutorial references: {{tutorial:name}}
    (re.compile(r'\{\{tutorial:([^}]+)\}\}'), r'<a href="/tutorials/\1" class="tutorial-link">\1</a>'),
    
    # External docs: {{external:name}}  
    (re.compile(r'\{\{external:([^}]+)\}\}'), r'<a href="https://docs.example.com/\1" rel="nofollow">\1</a>'),
]

processor = markdown2.Markdown(
    extras={
        "link-patterns": doc_patterns,
        "markdown-file-links": None,
        "header-ids": None,
        "toc": None,
        "tables": None
    }
)

documentation_html = processor.convert(doc_content)

External Link Behavior

Control how external links are opened by adding target attributes automatically.

# target-blank-links extra - add target="_blank" to external links
extras = ["target-blank-links"]

Usage Examples:

import markdown2

content = '''
# Links Demo

[Internal link](./local-page.md)
[External link](https://example.com)
[Another external](https://github.com/user/repo)
'''

html = markdown2.markdown(content, extras=["target-blank-links"])
# External links get target="_blank" attribute automatically
# Internal/relative links remain unchanged

Blog Processing with Auto-Links

import markdown2
import re

# Blog-style auto-linking
blog_patterns = [
    # Tag links: #tag
    (re.compile(r'(?<!\w)#([a-zA-Z0-9_]+)'), r'<a href="/tags/\1" class="tag-link">#\1</a>'),
    
    # Category links: [category:name]
    (re.compile(r'\[category:([^]]+)\]'), r'<a href="/category/\1" class="category-link">\1</a>'),
]

blog_processor = markdown2.Markdown(
    extras={
        "link-patterns": blog_patterns,
        "nofollow": None,  # Add nofollow to external links
        "smarty-pants": None,  # Nice typography
        "break-on-newline": None  # GitHub-style line breaks
    }
)

blog_html = blog_processor.convert(blog_post_content)

Install with Tessl CLI

npx tessl i tessl/pypi-markdown2

docs

code-syntax-extras.md

core-conversion.md

index.md

link-reference-extras.md

processor-classes.md

special-content-extras.md

structure-layout-extras.md

text-processing-extras.md

tile.json