marktripy 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. marktripy-1.0.3/.gitignore +90 -0
  2. marktripy-1.0.3/PKG-INFO +320 -0
  3. marktripy-1.0.3/README.md +296 -0
  4. marktripy-1.0.3/pyproject.toml +200 -0
  5. marktripy-1.0.3/src/marktripy/__init__.py +10 -0
  6. marktripy-1.0.3/src/marktripy/_version.py +21 -0
  7. marktripy-1.0.3/src/marktripy/core/__init__.py +7 -0
  8. marktripy-1.0.3/src/marktripy/core/ast.py +274 -0
  9. marktripy-1.0.3/src/marktripy/core/parser.py +199 -0
  10. marktripy-1.0.3/src/marktripy/core/validator.py +266 -0
  11. marktripy-1.0.3/src/marktripy/extensions/__init__.py +2 -0
  12. marktripy-1.0.3/src/marktripy/extensions/base.py +247 -0
  13. marktripy-1.0.3/src/marktripy/extensions/gfm.py +106 -0
  14. marktripy-1.0.3/src/marktripy/extensions/kbd.py +153 -0
  15. marktripy-1.0.3/src/marktripy/extensions/strikethrough.py +124 -0
  16. marktripy-1.0.3/src/marktripy/extensions/tasklist.py +138 -0
  17. marktripy-1.0.3/src/marktripy/parsers/__init__.py +2 -0
  18. marktripy-1.0.3/src/marktripy/parsers/markdown_it.py +352 -0
  19. marktripy-1.0.3/src/marktripy/parsers/mistletoe_parser.py +349 -0
  20. marktripy-1.0.3/src/marktripy/renderers/__init__.py +2 -0
  21. marktripy-1.0.3/src/marktripy/renderers/base.py +214 -0
  22. marktripy-1.0.3/src/marktripy/renderers/html.py +366 -0
  23. marktripy-1.0.3/src/marktripy/renderers/markdown.py +446 -0
  24. marktripy-1.0.3/src/marktripy/transformers/__init__.py +2 -0
  25. marktripy-1.0.3/src/marktripy/transformers/base.py +226 -0
  26. marktripy-1.0.3/src/marktripy/transformers/heading.py +217 -0
  27. marktripy-1.0.3/src/marktripy/transformers/id_generator.py +217 -0
  28. marktripy-1.0.3/src/marktripy/transformers/link_reference.py +258 -0
  29. marktripy-1.0.3/src/marktripy/transformers/toc.py +299 -0
  30. marktripy-1.0.3/src/marktripy/utils/__init__.py +2 -0
  31. marktripy-1.0.3/src/marktripy/utils/slugify.py +177 -0
  32. marktripy-1.0.3/tests/__init__.py +2 -0
  33. marktripy-1.0.3/tests/test_basic.py +254 -0
  34. marktripy-1.0.3/tests/test_benchmark.py +254 -0
  35. marktripy-1.0.3/tests/test_gfm_extensions.py +221 -0
  36. marktripy-1.0.3/tests/test_hypothesis.py +317 -0
  37. marktripy-1.0.3/tests/test_kbd_extension.py +206 -0
  38. marktripy-1.0.3/tests/test_roundtrip.py +405 -0
  39. marktripy-1.0.3/tests/test_transformers.py +424 -0
@@ -0,0 +1,90 @@
1
+ __pycache__/
2
+ __pypackages__/
3
+ .cache
4
+ .coverage
5
+ .coverage.*
6
+ .dmypy.json
7
+ .DS_Store
8
+ .eggs/
9
+ .env
10
+ .hypothesis/
11
+ .idea/
12
+ .installed.cfg
13
+ .ipynb_checkpoints
14
+ .mypy_cache/
15
+ .nox/
16
+ .pdm-python
17
+ .pdm.toml
18
+ .pybuilder/
19
+ .pyre/
20
+ .pytest_cache/
21
+ .Python
22
+ .python-version
23
+ .pytype/
24
+ .ropeproject
25
+ .scrapy
26
+ .spyderproject
27
+ .spyproject
28
+ .tox/
29
+ .venv
30
+ .vscode/
31
+ .webassets-cache
32
+ *.cover
33
+ *.egg
34
+ *.egg-info/
35
+ *.log
36
+ *.manifest
37
+ *.mo
38
+ *.pot
39
+ *.py,cover
40
+ *.py[cod]
41
+ *.sage.py
42
+ *.so
43
+ *.spec
44
+ *$py.class
45
+ /site
46
+ build/
47
+ celerybeat-schedule
48
+ celerybeat.pid
49
+ cover/
50
+ coverage.xml
51
+ cython_debug/
52
+ db.sqlite3
53
+ db.sqlite3-journal
54
+ debug_tokens.py
55
+ develop-eggs/
56
+ dist/
57
+ dmypy.json
58
+ docs/_build/
59
+ downloads/
60
+ eggs/
61
+ env.bak/
62
+ env/
63
+ ENV/
64
+ htmlcov/
65
+ instance/
66
+ ipython_config.py
67
+ lib/
68
+ lib64/
69
+ llms.txt
70
+ local_settings.py
71
+ MANIFEST
72
+ nosetests.xml
73
+ parts/
74
+ pdm.lock
75
+ pip-delete-this-directory.txt
76
+ pip-log.txt
77
+ Pipfile.lock
78
+ poetry.lock
79
+ profile_default/
80
+ sdist/
81
+ share/python-wheels/
82
+ target/
83
+ uv.lock
84
+ var/
85
+ venv.bak/
86
+ venv/
87
+ wheels/
88
+
89
+ # Generated version file
90
+ src/marktripy/_version.py
@@ -0,0 +1,320 @@
1
+ Metadata-Version: 2.4
2
+ Name: marktripy
3
+ Version: 1.0.3
4
+ Summary: A Python package for converting Markdown to AST and back to Markdown
5
+ Project-URL: Homepage, https://github.com/twardoch/marktripy
6
+ Project-URL: Repository, https://github.com/twardoch/marktripy
7
+ Project-URL: Issues, https://github.com/twardoch/marktripy/issues
8
+ Author-email: Adam <adam@example.com>
9
+ License: MIT
10
+ Keywords: ast,commonmark,converter,markdown,parser
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Topic :: Text Processing :: Markup
17
+ Requires-Python: >=3.12
18
+ Requires-Dist: fire>=0.7.0
19
+ Requires-Dist: loguru>=0.7.3
20
+ Requires-Dist: markdown-it-py[linkify,plugins]>=3.0.0
21
+ Requires-Dist: mistletoe>=1.4.0
22
+ Requires-Dist: rich>=14.1.0
23
+ Description-Content-Type: text/markdown
24
+
25
+ # marktripy
26
+
27
+ **TL;DR**: A Python package for parsing Markdown to AST, manipulating the tree structure, and serializing back to Markdown while preserving formatting. Built on `markdown-it-py` and `mistletoe` for maximum flexibility.
28
+
29
+ ```python
30
+ from marktripy import parse_markdown, render_markdown
31
+
32
+ # Parse Markdown to AST
33
+ ast = parse_markdown("# Hello\n\nThis is **bold** text.")
34
+
35
+ # Manipulate AST (e.g., downgrade headings)
36
+ for node in ast.walk():
37
+ if node.type == "heading":
38
+ node.level += 1
39
+
40
+ # Render back to Markdown
41
+ markdown = render_markdown(ast)
42
+ # Output: "## Hello\n\nThis is **bold** text."
43
+ ```
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ # Using pip
49
+ pip install marktripy
50
+
51
+ # Using uv (recommended)
52
+ uv add marktripy
53
+
54
+ # Development installation
55
+ git clone https://github.com/yourusername/marktripy
56
+ cd marktripy
57
+ uv sync --dev
58
+ ```
59
+
60
+ ## Quick Usage
61
+
62
+ ### Basic Markdown to HTML
63
+
64
+ ```python
65
+ from marktripy import markdown_to_html
66
+
67
+ html = markdown_to_html("# Hello World\n\nThis is **bold** and *italic*.")
68
+ # <h1>Hello World</h1><p>This is <strong>bold</strong> and <em>italic</em>.</p>
69
+ ```
70
+
71
+ ### AST Manipulation
72
+
73
+ ```python
74
+ from marktripy import parse_markdown, render_markdown
75
+
76
+ # Parse Markdown to AST
77
+ ast = parse_markdown("""
78
+ # Main Title
79
+ ## Section 1
80
+ Some content here.
81
+ ## Section 2
82
+ More content.
83
+ """)
84
+
85
+ # Add IDs to all headings
86
+ for node in ast.walk():
87
+ if node.type == "heading":
88
+ # Generate ID from heading text
89
+ text = node.get_text().lower().replace(" ", "-")
90
+ node.attrs["id"] = text
91
+
92
+ # Downgrade all headings by one level
93
+ for node in ast.walk():
94
+ if node.type == "heading" and node.level < 6:
95
+ node.level += 1
96
+
97
+ # Render back to Markdown
98
+ result = render_markdown(ast)
99
+ ```
100
+
101
+ ### Custom Syntax Extensions
102
+
103
+ ```python
104
+ from marktripy import create_extension, Parser
105
+
106
+ # Create a custom extension for ++text++ → <kbd>text</kbd>
107
+ kbd_extension = create_extension(
108
+ pattern=r'\+\+([^+]+)\+\+',
109
+ node_type='kbd',
110
+ html_tag='kbd'
111
+ )
112
+
113
+ # Use parser with extension
114
+ parser = Parser(extensions=[kbd_extension])
115
+ ast = parser.parse("Press ++Ctrl+C++ to copy")
116
+ html = parser.render_html(ast)
117
+ # Output: Press <kbd>Ctrl+C</kbd> to copy
118
+ ```
119
+
120
+ ### CLI Usage
121
+
122
+ ```bash
123
+ # Convert Markdown to HTML
124
+ marktripy convert input.md -o output.html
125
+
126
+ # Parse and manipulate Markdown
127
+ marktripy transform input.md --downgrade-headings --add-ids -o output.md
128
+
129
+ # Validate Markdown structure
130
+ marktripy validate document.md --check-links --check-headings
131
+ ```
132
+
133
+ ## The Backstory
134
+
135
+ ### Why Another Markdown Parser?
136
+
137
+ The Python ecosystem has numerous Markdown parsers, each with different strengths:
138
+
139
+ - **`markdown`**: The original, extensible but with a complex API
140
+ - **`markdown2`**: Faster alternative but less extensible
141
+ - **`mistune`**: Fast and supports AST, but limited round-trip capability
142
+ - **`marko`**: Good AST support but newer with less ecosystem
143
+ - **`markdown-it-py`**: Port of markdown-it with excellent plugin system
144
+
145
+ After extensive research (see `/ref` directory), I found that no single library perfectly addressed the need for:
146
+
147
+ 1. **Clean AST manipulation** - Easy traversal and modification of document structure
148
+ 2. **Round-trip conversion** - Parse Markdown → AST → Markdown without losing formatting
149
+ 3. **Extensibility** - Simple API for adding custom syntax
150
+ 4. **Performance** - Fast enough for real-world documents
151
+ 5. **Standards compliance** - CommonMark compliant with GFM extensions
152
+
153
+ ### The Research Journey
154
+
155
+ The `/ref` directory contains comprehensive research comparing 8+ Python Markdown libraries across multiple dimensions:
156
+
157
+ - **ref1.md**: Practical guide to advanced Markdown processing in Python
158
+ - **ref2.md**: Detailed comparison of parser architectures and extension mechanisms
159
+ - **ref3.md**: Performance benchmarks and feature matrix
160
+
161
+ Key findings:
162
+
163
+ - `markdown-it-py` offers the best plugin architecture
164
+ - `mistletoe` has the cleanest AST representation
165
+ - `marko` provides good round-trip capabilities
166
+ - Performance varies by 10-100x between libraries
167
+
168
+ ### Design Philosophy
169
+
170
+ `marktripy` combines the best ideas from existing libraries:
171
+
172
+ 1. **Dual-parser architecture**: Use `markdown-it-py` for extensibility and `mistletoe` for AST manipulation
173
+ 2. **Unified AST format**: Convert between parser representations transparently
174
+ 3. **Preserving formatting**: Track source positions and whitespace for faithful round-trips
175
+ 4. **Plugin-first design**: Everything beyond core CommonMark is a plugin
176
+ 5. **Type safety**: Full type hints with `mypy --strict` compatibility
177
+
178
+ ## Technical Architecture
179
+
180
+ ### Core Components
181
+
182
+ ```text
183
+ marktripy/
184
+ ├── ast.py # Unified AST node definitions
185
+ ├── parser.py # Parser abstraction layer
186
+ ├── renderer.py # Markdown/HTML renderers
187
+ ├── extensions/ # Built-in extensions
188
+ │ ├── gfm.py # GitHub Flavored Markdown
189
+ │ ├── toc.py # Table of contents generator
190
+ │ └── ...
191
+ ├── transformers/ # AST transformation utilities
192
+ │ ├── headings.py # Heading manipulation
193
+ │ ├── links.py # Link processing
194
+ │ └── ...
195
+ └── cli.py # Command-line interface
196
+ ```
197
+
198
+ ### AST Structure
199
+
200
+ The AST uses a unified node structure compatible with both parsers:
201
+
202
+ ```python
203
+ class ASTNode:
204
+ type: str # Node type (heading, paragraph, etc.)
205
+ children: List[ASTNode]
206
+ attrs: Dict[str, Any] # Attributes (id, class, etc.)
207
+ content: str # Text content for leaf nodes
208
+ meta: Dict[str, Any] # Source mapping, parser-specific data
209
+ ```
210
+
211
+ ### Parser Architecture
212
+
213
+ ```python
214
+ # Abstraction layer over multiple parsers
215
+ class Parser:
216
+ def __init__(self, parser_backend="markdown-it-py", extensions=None):
217
+ self.backend = self._create_backend(parser_backend)
218
+ self.extensions = extensions or []
219
+
220
+ def parse(self, markdown: str) -> ASTNode:
221
+ # Parse with backend
222
+ backend_ast = self.backend.parse(markdown)
223
+ # Convert to unified AST
224
+ return self._normalize_ast(backend_ast)
225
+ ```
226
+
227
+ ### Extension System
228
+
229
+ Extensions can hook into multiple stages:
230
+
231
+ ```python
232
+ class Extension:
233
+ def extend_parser(self, parser): ... # Modify parser rules
234
+ def transform_ast(self, ast): ... # Post-process AST
235
+ def extend_renderer(self, renderer): ... # Custom rendering
236
+ ```
237
+
238
+ ### Rendering Pipeline
239
+
240
+ 1. **AST → Markdown**: Preserves formatting, handles custom nodes
241
+ 2. **AST → HTML**: Configurable sanitization, custom handlers
242
+ 3. **AST → JSON**: Serialization for processing pipelines
243
+
244
+ ### Performance Optimizations
245
+
246
+ - Lazy parsing for large documents
247
+ - Streaming renderers for memory efficiency
248
+ - Optional C extensions via `umarkdown` backend
249
+ - Caching for repeated transformations
250
+
251
+ ## Advanced Usage
252
+
253
+ ### Custom Transformers
254
+
255
+ ```python
256
+ from marktripy import Transformer
257
+
258
+ class HeaderAnchorTransformer(Transformer):
259
+ """Add GitHub-style anchor links to headers"""
260
+
261
+ def transform(self, ast):
262
+ for node in ast.walk():
263
+ if node.type == "heading":
264
+ anchor = self.create_anchor(node)
265
+ node.children.insert(0, anchor)
266
+ return ast
267
+ ```
268
+
269
+ ### Parser Backends
270
+
271
+ ```python
272
+ # Use different backends for different needs
273
+ from marktripy import Parser
274
+
275
+ # Maximum compatibility
276
+ parser = Parser(backend="markdown")
277
+
278
+ # Best performance
279
+ parser = Parser(backend="mistletoe")
280
+
281
+ # Most extensions
282
+ parser = Parser(backend="markdown-it-py")
283
+ ```
284
+
285
+ ### Integration Examples
286
+
287
+ ```python
288
+ # Pelican static site generator
289
+ from marktripy import PelicanReader
290
+
291
+ # MkDocs documentation
292
+ from marktripy import MkDocsPlugin
293
+
294
+ # Jupyter notebook processing
295
+ from marktripy import MarkdownCell
296
+ ```
297
+
298
+ ## Contributing
299
+
300
+ We welcome contributions! Key areas:
301
+
302
+ - Additional extensions (math, diagrams, etc.)
303
+ - Performance improvements
304
+ - Better round-trip fidelity
305
+ - More transformer utilities
306
+
307
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
308
+
309
+ ## License
310
+
311
+ MIT License - see [LICENSE](LICENSE) for details.
312
+
313
+ ## Acknowledgments
314
+
315
+ Built on the shoulders of giants:
316
+
317
+ - `markdown-it-py` developers for the excellent plugin system
318
+ - `mistletoe` for the clean AST design
319
+ - The CommonMark specification authors
320
+ - All researchers of the Python Markdown ecosystem
@@ -0,0 +1,296 @@
1
+ # marktripy
2
+
3
+ **TL;DR**: A Python package for parsing Markdown to AST, manipulating the tree structure, and serializing back to Markdown while preserving formatting. Built on `markdown-it-py` and `mistletoe` for maximum flexibility.
4
+
5
+ ```python
6
+ from marktripy import parse_markdown, render_markdown
7
+
8
+ # Parse Markdown to AST
9
+ ast = parse_markdown("# Hello\n\nThis is **bold** text.")
10
+
11
+ # Manipulate AST (e.g., downgrade headings)
12
+ for node in ast.walk():
13
+ if node.type == "heading":
14
+ node.level += 1
15
+
16
+ # Render back to Markdown
17
+ markdown = render_markdown(ast)
18
+ # Output: "## Hello\n\nThis is **bold** text."
19
+ ```
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ # Using pip
25
+ pip install marktripy
26
+
27
+ # Using uv (recommended)
28
+ uv add marktripy
29
+
30
+ # Development installation
31
+ git clone https://github.com/yourusername/marktripy
32
+ cd marktripy
33
+ uv sync --dev
34
+ ```
35
+
36
+ ## Quick Usage
37
+
38
+ ### Basic Markdown to HTML
39
+
40
+ ```python
41
+ from marktripy import markdown_to_html
42
+
43
+ html = markdown_to_html("# Hello World\n\nThis is **bold** and *italic*.")
44
+ # <h1>Hello World</h1><p>This is <strong>bold</strong> and <em>italic</em>.</p>
45
+ ```
46
+
47
+ ### AST Manipulation
48
+
49
+ ```python
50
+ from marktripy import parse_markdown, render_markdown
51
+
52
+ # Parse Markdown to AST
53
+ ast = parse_markdown("""
54
+ # Main Title
55
+ ## Section 1
56
+ Some content here.
57
+ ## Section 2
58
+ More content.
59
+ """)
60
+
61
+ # Add IDs to all headings
62
+ for node in ast.walk():
63
+ if node.type == "heading":
64
+ # Generate ID from heading text
65
+ text = node.get_text().lower().replace(" ", "-")
66
+ node.attrs["id"] = text
67
+
68
+ # Downgrade all headings by one level
69
+ for node in ast.walk():
70
+ if node.type == "heading" and node.level < 6:
71
+ node.level += 1
72
+
73
+ # Render back to Markdown
74
+ result = render_markdown(ast)
75
+ ```
76
+
77
+ ### Custom Syntax Extensions
78
+
79
+ ```python
80
+ from marktripy import create_extension, Parser
81
+
82
+ # Create a custom extension for ++text++ → <kbd>text</kbd>
83
+ kbd_extension = create_extension(
84
+ pattern=r'\+\+([^+]+)\+\+',
85
+ node_type='kbd',
86
+ html_tag='kbd'
87
+ )
88
+
89
+ # Use parser with extension
90
+ parser = Parser(extensions=[kbd_extension])
91
+ ast = parser.parse("Press ++Ctrl+C++ to copy")
92
+ html = parser.render_html(ast)
93
+ # Output: Press <kbd>Ctrl+C</kbd> to copy
94
+ ```
95
+
96
+ ### CLI Usage
97
+
98
+ ```bash
99
+ # Convert Markdown to HTML
100
+ marktripy convert input.md -o output.html
101
+
102
+ # Parse and manipulate Markdown
103
+ marktripy transform input.md --downgrade-headings --add-ids -o output.md
104
+
105
+ # Validate Markdown structure
106
+ marktripy validate document.md --check-links --check-headings
107
+ ```
108
+
109
+ ## The Backstory
110
+
111
+ ### Why Another Markdown Parser?
112
+
113
+ The Python ecosystem has numerous Markdown parsers, each with different strengths:
114
+
115
+ - **`markdown`**: The original, extensible but with a complex API
116
+ - **`markdown2`**: Faster alternative but less extensible
117
+ - **`mistune`**: Fast and supports AST, but limited round-trip capability
118
+ - **`marko`**: Good AST support but newer with less ecosystem
119
+ - **`markdown-it-py`**: Port of markdown-it with excellent plugin system
120
+
121
+ After extensive research (see `/ref` directory), I found that no single library perfectly addressed the need for:
122
+
123
+ 1. **Clean AST manipulation** - Easy traversal and modification of document structure
124
+ 2. **Round-trip conversion** - Parse Markdown → AST → Markdown without losing formatting
125
+ 3. **Extensibility** - Simple API for adding custom syntax
126
+ 4. **Performance** - Fast enough for real-world documents
127
+ 5. **Standards compliance** - CommonMark compliant with GFM extensions
128
+
129
+ ### The Research Journey
130
+
131
+ The `/ref` directory contains comprehensive research comparing 8+ Python Markdown libraries across multiple dimensions:
132
+
133
+ - **ref1.md**: Practical guide to advanced Markdown processing in Python
134
+ - **ref2.md**: Detailed comparison of parser architectures and extension mechanisms
135
+ - **ref3.md**: Performance benchmarks and feature matrix
136
+
137
+ Key findings:
138
+
139
+ - `markdown-it-py` offers the best plugin architecture
140
+ - `mistletoe` has the cleanest AST representation
141
+ - `marko` provides good round-trip capabilities
142
+ - Performance varies by 10-100x between libraries
143
+
144
+ ### Design Philosophy
145
+
146
+ `marktripy` combines the best ideas from existing libraries:
147
+
148
+ 1. **Dual-parser architecture**: Use `markdown-it-py` for extensibility and `mistletoe` for AST manipulation
149
+ 2. **Unified AST format**: Convert between parser representations transparently
150
+ 3. **Preserving formatting**: Track source positions and whitespace for faithful round-trips
151
+ 4. **Plugin-first design**: Everything beyond core CommonMark is a plugin
152
+ 5. **Type safety**: Full type hints with `mypy --strict` compatibility
153
+
154
+ ## Technical Architecture
155
+
156
+ ### Core Components
157
+
158
+ ```text
159
+ marktripy/
160
+ ├── ast.py # Unified AST node definitions
161
+ ├── parser.py # Parser abstraction layer
162
+ ├── renderer.py # Markdown/HTML renderers
163
+ ├── extensions/ # Built-in extensions
164
+ │ ├── gfm.py # GitHub Flavored Markdown
165
+ │ ├── toc.py # Table of contents generator
166
+ │ └── ...
167
+ ├── transformers/ # AST transformation utilities
168
+ │ ├── headings.py # Heading manipulation
169
+ │ ├── links.py # Link processing
170
+ │ └── ...
171
+ └── cli.py # Command-line interface
172
+ ```
173
+
174
+ ### AST Structure
175
+
176
+ The AST uses a unified node structure compatible with both parsers:
177
+
178
+ ```python
179
+ class ASTNode:
180
+ type: str # Node type (heading, paragraph, etc.)
181
+ children: List[ASTNode]
182
+ attrs: Dict[str, Any] # Attributes (id, class, etc.)
183
+ content: str # Text content for leaf nodes
184
+ meta: Dict[str, Any] # Source mapping, parser-specific data
185
+ ```
186
+
187
+ ### Parser Architecture
188
+
189
+ ```python
190
+ # Abstraction layer over multiple parsers
191
+ class Parser:
192
+ def __init__(self, parser_backend="markdown-it-py", extensions=None):
193
+ self.backend = self._create_backend(parser_backend)
194
+ self.extensions = extensions or []
195
+
196
+ def parse(self, markdown: str) -> ASTNode:
197
+ # Parse with backend
198
+ backend_ast = self.backend.parse(markdown)
199
+ # Convert to unified AST
200
+ return self._normalize_ast(backend_ast)
201
+ ```
202
+
203
+ ### Extension System
204
+
205
+ Extensions can hook into multiple stages:
206
+
207
+ ```python
208
+ class Extension:
209
+ def extend_parser(self, parser): ... # Modify parser rules
210
+ def transform_ast(self, ast): ... # Post-process AST
211
+ def extend_renderer(self, renderer): ... # Custom rendering
212
+ ```
213
+
214
+ ### Rendering Pipeline
215
+
216
+ 1. **AST → Markdown**: Preserves formatting, handles custom nodes
217
+ 2. **AST → HTML**: Configurable sanitization, custom handlers
218
+ 3. **AST → JSON**: Serialization for processing pipelines
219
+
220
+ ### Performance Optimizations
221
+
222
+ - Lazy parsing for large documents
223
+ - Streaming renderers for memory efficiency
224
+ - Optional C extensions via `umarkdown` backend
225
+ - Caching for repeated transformations
226
+
227
+ ## Advanced Usage
228
+
229
+ ### Custom Transformers
230
+
231
+ ```python
232
+ from marktripy import Transformer
233
+
234
+ class HeaderAnchorTransformer(Transformer):
235
+ """Add GitHub-style anchor links to headers"""
236
+
237
+ def transform(self, ast):
238
+ for node in ast.walk():
239
+ if node.type == "heading":
240
+ anchor = self.create_anchor(node)
241
+ node.children.insert(0, anchor)
242
+ return ast
243
+ ```
244
+
245
+ ### Parser Backends
246
+
247
+ ```python
248
+ # Use different backends for different needs
249
+ from marktripy import Parser
250
+
251
+ # Maximum compatibility
252
+ parser = Parser(backend="markdown")
253
+
254
+ # Best performance
255
+ parser = Parser(backend="mistletoe")
256
+
257
+ # Most extensions
258
+ parser = Parser(backend="markdown-it-py")
259
+ ```
260
+
261
+ ### Integration Examples
262
+
263
+ ```python
264
+ # Pelican static site generator
265
+ from marktripy import PelicanReader
266
+
267
+ # MkDocs documentation
268
+ from marktripy import MkDocsPlugin
269
+
270
+ # Jupyter notebook processing
271
+ from marktripy import MarkdownCell
272
+ ```
273
+
274
+ ## Contributing
275
+
276
+ We welcome contributions! Key areas:
277
+
278
+ - Additional extensions (math, diagrams, etc.)
279
+ - Performance improvements
280
+ - Better round-trip fidelity
281
+ - More transformer utilities
282
+
283
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
284
+
285
+ ## License
286
+
287
+ MIT License - see [LICENSE](LICENSE) for details.
288
+
289
+ ## Acknowledgments
290
+
291
+ Built on the shoulders of giants:
292
+
293
+ - `markdown-it-py` developers for the excellent plugin system
294
+ - `mistletoe` for the clean AST design
295
+ - The CommonMark specification authors
296
+ - All researchers of the Python Markdown ecosystem