Troubleshooting#
Diagnose common Wenmode integration issues around raw HTML, URL sanitization, directives, streaming, custom renderers, and rule selection.
Use this page when Wenmode runs successfully but the rendered output or AST does not match what you expected. If you are still choosing a dialect, start with Presets and Rule matrix instead.
Raw HTML is escaped#
HTMLRenderer() escapes raw HTML nodes by default. This is the recommended
setting for user-authored Markdown.
Use raw HTML passthrough only for trusted or separately sanitized content:
from wenmode import HTMLRenderer, Wenmode
wen = Wenmode(renderer=HTMLRenderer(escape=False))
If you do not want raw HTML syntax to become html nodes at all, remove
HtmlBlock and RawHtml from the rule list. See Security.
Links render without href#
HTMLRenderer() drops unsafe URL schemes by default. For example,
javascript: links render without href.
from wenmode import Wenmode
html = Wenmode().render('[x](javascript:alert(1))')
assert html == '<p><a>x</a></p>\n'
Use HTMLRenderer(sanitize_urls=False) only when URL validation is handled
outside Wenmode.
A directive parses but does not render custom HTML#
Directive syntax rules and directive renderers are separate. Enabling
ContainerDirective, LeafDirective, TextDirective, or the
wenmode.plugins.fenced_directive and wenmode.plugins.inline_role plugins
only creates directive nodes. Register a directive renderer when you want
special HTML output.
from wenmode import Wenmode
from wenmode.directives import Admonition
from wenmode.rules import ContainerDirective
wen = Wenmode([ContainerDirective], directives=[Admonition()])
Without a matching directive renderer, Wenmode falls back to rendering
directive children. literalDirective nodes fall back to escaped literal text,
and code-block literal directives have default code-block output in the HTML
renderer.
A custom renderer handler is not called#
Renderer dispatch uses the node’s type string. Check the AST with
root.to_ast() and register that exact value:
from wenmode import Wenmode
root = Wenmode().parse('**strong**')
assert root.to_ast()['children'][0]['children'][0]['type'] == 'strong'
For custom nodes, set a stable type value and register handlers from your
plugin setup function. See Custom Plugins.
Streaming raises StreamingUnsupportedError#
Streaming cannot use rules that resolve inline content after the whole document
has been parsed. Use the streaming preset:
from wenmode import Wenmode
from wenmode.presets import streaming
wen = Wenmode(streaming)
If you build a custom streaming rule list, avoid Footnote,
wenmode.plugins.abbr, Link(references=True), and Image(references=True).
See Rule matrix.
Inspect the configured parser when the blocker is not obvious:
from wenmode import Wenmode
from wenmode.presets import github
wen = Wenmode(github)
assert wen.supports_streaming is False
assert wen.streaming_blockers() == ['footnote', 'reference']
GFM syntax is not recognized#
Wenmode() uses the commonmark preset. Switch to github for the full GFM
set, or enable the individual standard rules listed in Rule matrix.
from wenmode import Wenmode
from wenmode.presets import github
wen = Wenmode(github)
Reference-style links stay as text#
Reference-style links need Link(references=True) and collected reference
definitions. The streaming preset disables references so it can emit output
incrementally.
Use commonmark or github for full-document reference-style link support, or
use direct links in streaming responses.