Peter Hoffmann

Mistune 3 Wikilink Inline Parser

Mistune 3 has changed its internal structure and extension mechanisms.

The Mistune advanced documentation provides several examples of how to create and register inline patterns. After a few iterations, I developed the following solution to render wikilinks:

import re  
from typing import Match  
  
from mistune import Markdown  
from mistune.core import BaseRenderer, InlineState  
from mistune.inline_parser import InlineParser  

  
def parse_wikilink(inline: "InlineParser", m: Match[str], state: "InlineState") -> int:  
    """Parse wikilink syntax [[page title]] or [[page title|display text]]."""  
    page_title = m.group('page').strip()  
    display_text = m.group('display')  
      
    # Use display text if provided; otherwise, use page title  
    if display_text is not None:  
        text = display_text.strip()  
    else:  
        text = page_title  
      
    # Create a wikilink token  
    state.append_token({  
        "type": "wikilink",  
        "children": [{"type": "text", "raw": text}],  
        "attrs": {  
            "page": page_title,  
            "display": text  
        }  
    })  
      
    return m.end()  
  
def render_wikilink_html(renderer: "BaseRenderer", children: str, page: str, display: str) -> str:  
    """Render a wikilink as an HTML anchor tag."""  
    url_page = page.replace(' ', '_')  
    return f'<a href="/wiki/{url_page}" class="wikilink">{children}</a>'  
  
def wikilink_plugin(md: "Markdown") -> None:  
    """Plugin function to add wikilink support to Mistune."""  
    # Use named groups
    WIKILINK_PATTERN = r'\[\[(?P<page>[^|\]]+)(?:\|(?P<display>[^\]]+))?\]\]'  
    md.inline.register("wikilink", WIKILINK_PATTERN, parse_wikilink, before="link")  
      
    if md.renderer and md.renderer.NAME == "html":  
        md.renderer.register("wikilink", render_wikilink_html)

To test it, you can run the following code:

from mistune import create_markdown  
    
# Create a Markdown parser with the wikilink plugin  
md = create_markdown(plugins=[wikilink_plugin])  
    
# Test examples  
text1 = "Check out [[Main Page]] for more info."  
text2 = "Visit [[Installation Guide|the installation guide]] to get started."  
text3 = "Multiple links: [[Page One]] and [[Page Two|Custom Text]]."  
    
print("Example 1:")  
print(md(text1))  
# Output: <p>Check out <a href="/wiki/Main_Page" class="wikilink">Main Page</a> for more info.</p>  
    
print("\nExample 2:")  
print(md(text2))  
# Output: <p>Visit <a href="/wiki/Installation_Guide" class="wikilink">the installation guide</a> to get started.</p>  
    
print("\nExample 3:")  
print(md(text3))  
# Output: <p>Multiple links: <a href="/wiki/Page_One" class="wikilink">Page One</a> and <a href="/wiki/Page_Two" class="wikilink">Custom Text</a>.</p>