Python parser for the CommonMark Markdown spec
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Utility functions for debugging, AST inspection, and format conversion. These tools help with development, testing, and understanding the structure of parsed documents.
Functions for converting AST nodes to different representations for debugging and serialization purposes.
def dumpAST(obj, ind=0, topnode=False):
"""
Print a pretty-printed representation of an AST to console.
Args:
obj (Node): AST node to print
ind (int): Current indentation level (used internally for recursion)
topnode (bool): Whether this is the top-level node (used internally)
Returns:
None: Prints directly to console
"""
def dumpJSON(obj):
"""
Convert an AST to JSON string representation.
Args:
obj (Node): AST node to convert
Returns:
str: JSON representation of the AST
"""Helper functions for working with AST nodes and determining their properties.
def is_container(node):
"""
Check if a node type can contain child nodes.
Args:
node (Node): Node to check
Returns:
bool: True if the node can have children, False otherwise
"""from commonmark import Parser, dumpAST
parser = Parser()
markdown = """
# Title
Some text with **bold** and *italic* formatting.
- List item 1
- List item 2
"""
ast = parser.parse(markdown)
dumpAST(ast)
# Output: Hierarchical representation of the AST structurefrom commonmark import Parser, dumpJSON
import json
parser = Parser()
markdown = "# Hello\n*World*"
ast = parser.parse(markdown)
json_string = dumpJSON(ast)
print(json_string)
# Parse back to Python dict for manipulation
ast_dict = json.loads(json_string)
print(f"Root node type: {ast_dict[0]['type']}")from commonmark import Parser
from commonmark.node import is_container
parser = Parser()
ast = parser.parse("# Title\n\nParagraph text")
# Walk through nodes and check if they can contain children
walker = ast.walker()
event = walker.nxt()
while event:
node, entering = event['node'], event['entering']
if entering:
can_contain = is_container(node)
print(f"{node.t}: {'container' if can_contain else 'leaf'}")
event = walker.nxt()from commonmark import Parser, dumpAST, dumpJSON
parser = Parser()
complex_markdown = """
# Main Title
## Subsection
Here's a paragraph with **bold**, *italic*, and `code` text.
```python
def hello():
print("Hello, world!")This is a blockquote with multiple lines. """
ast = parser.parse(complex_markdown)
print("=== AST Structure ===") dumpAST(ast)
print("\n=== JSON Representation ===") json_repr = dumpJSON(ast) print(json_repr[:200] + "..." if len(json_repr) > 200 else json_repr)
### Analyzing Node Properties
```python
from commonmark import Parser
from commonmark.node import is_container
parser = Parser()
ast = parser.parse("""
# Title
Paragraph with **bold** text.
- Item 1
- Item 2
""")
def analyze_node(node, depth=0):
indent = " " * depth
print(f"{indent}{node.t}")
if hasattr(node, 'literal') and node.literal:
print(f"{indent} literal: '{node.literal}'")
if is_container(node):
print(f"{indent} (container)")
child = node.first_child
while child:
analyze_node(child, depth + 1)
child = child.nxt
else:
print(f"{indent} (leaf)")
analyze_node(ast)When debugging AST structures, you'll encounter these common node types:
document: Root node of the documentparagraph: Paragraph blockheading: Header (h1-h6)text: Plain text contentstrong: Bold textemph: Italic textcode: Inline codecode_block: Code blocklist: Ordered or unordered listitem: List itemlink: Hyperlinkimage: Imageblock_quote: Blockquotethematic_break: Horizontal rulehtml_inline: Inline HTMLhtml_block: Block-level HTMLInstall with Tessl CLI
npx tessl i tessl/pypi-commonmark