markdownpal 0.1.0__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 (33) hide show
  1. markdownpal-0.1.0/.claude/settings.local.json +14 -0
  2. markdownpal-0.1.0/.gitignore +8 -0
  3. markdownpal-0.1.0/EXAMPLES.md +201 -0
  4. markdownpal-0.1.0/LICENSE +21 -0
  5. markdownpal-0.1.0/PKG-INFO +261 -0
  6. markdownpal-0.1.0/README.md +216 -0
  7. markdownpal-0.1.0/docs/superpowers/plans/2026-04-12-markdownpal.md +1035 -0
  8. markdownpal-0.1.0/docs/superpowers/specs/2026-04-12-markdownpal-design.md +195 -0
  9. markdownpal-0.1.0/main.py +22 -0
  10. markdownpal-0.1.0/markdownpal/__init__.py +23 -0
  11. markdownpal-0.1.0/markdownpal/blocks/__init__.py +17 -0
  12. markdownpal-0.1.0/markdownpal/blocks/base.py +8 -0
  13. markdownpal-0.1.0/markdownpal/blocks/code.py +10 -0
  14. markdownpal-0.1.0/markdownpal/blocks/heading.py +49 -0
  15. markdownpal-0.1.0/markdownpal/blocks/list_.py +30 -0
  16. markdownpal-0.1.0/markdownpal/blocks/media.py +19 -0
  17. markdownpal-0.1.0/markdownpal/blocks/table.py +21 -0
  18. markdownpal-0.1.0/markdownpal/blocks/text.py +30 -0
  19. markdownpal-0.1.0/markdownpal/document.py +18 -0
  20. markdownpal-0.1.0/markdownpal/inline.py +14 -0
  21. markdownpal-0.1.0/pyproject.toml +38 -0
  22. markdownpal-0.1.0/tests/__init__.py +0 -0
  23. markdownpal-0.1.0/tests/blocks/__init__.py +0 -0
  24. markdownpal-0.1.0/tests/blocks/test_code.py +17 -0
  25. markdownpal-0.1.0/tests/blocks/test_heading.py +29 -0
  26. markdownpal-0.1.0/tests/blocks/test_list.py +29 -0
  27. markdownpal-0.1.0/tests/blocks/test_media.py +17 -0
  28. markdownpal-0.1.0/tests/blocks/test_table.py +36 -0
  29. markdownpal-0.1.0/tests/blocks/test_text.py +25 -0
  30. markdownpal-0.1.0/tests/test_document.py +51 -0
  31. markdownpal-0.1.0/tests/test_inline.py +25 -0
  32. markdownpal-0.1.0/tests/test_integration.py +48 -0
  33. markdownpal-0.1.0/uv.lock +199 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git add:*)",
5
+ "Bash(git commit:*)",
6
+ "Bash(python:*)",
7
+ "Bash(.venv/bin/pip install:*)",
8
+ "Bash(/Users/hanchaoran/Documents/yeyecha/markdownpal/.venv/bin/pip install:*)",
9
+ "Bash(/Users/hanchaoran/Documents/yeyecha/markdownpal/.venv/bin/python:*)",
10
+ "Bash(python3:*)",
11
+ "Bash(.venv/bin/pytest:*)"
12
+ ]
13
+ }
14
+ }
@@ -0,0 +1,8 @@
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ .idea/
6
+ dist/
7
+ *.egg-info/
8
+ .DS_Store
@@ -0,0 +1,201 @@
1
+ # MarkdownPal Examples
2
+
3
+ ## Quick Start
4
+
5
+ ```python
6
+ from markdownpal import Document
7
+ from markdownpal.blocks import H1Block, TextBlock
8
+ from markdownpal.inline import bold
9
+
10
+ doc = Document()
11
+ doc.append(H1Block("Hello, MarkdownPal"))
12
+ doc.append(TextBlock(f"Build {bold('Markdown')} files with Python."))
13
+ doc.save("output.md")
14
+ ```
15
+
16
+ ---
17
+
18
+ ## Block Types
19
+
20
+ ### Headings
21
+
22
+ ```python
23
+ from markdownpal.blocks import H1Block, H2Block, H3Block, H4Block, H5Block, H6Block
24
+
25
+ doc.append(H1Block("Title")) # # Title
26
+ doc.append(H2Block("Section")) # ## Section
27
+ doc.append(H3Block("Subsection")) # ### Subsection
28
+ doc.append(H4Block("Detail")) # #### Detail
29
+ doc.append(H5Block("Minor")) # ##### Minor
30
+ doc.append(H6Block("Tiny")) # ###### Tiny
31
+ ```
32
+
33
+ ### Text & Formatting
34
+
35
+ ```python
36
+ from markdownpal.blocks import TextBlock, QuoteBlock, HRBlock, CommentBlock
37
+ from markdownpal.inline import bold, italic, code, strikethrough
38
+
39
+ doc.append(TextBlock("Plain paragraph."))
40
+ doc.append(TextBlock(f"{bold('Bold')}, {italic('italic')}, {code('inline code')}, {strikethrough('struck')}."))
41
+ doc.append(QuoteBlock("A quote that spans\nmultiple lines."))
42
+ doc.append(HRBlock())
43
+ doc.append(CommentBlock("This comment is invisible in rendered output."))
44
+ ```
45
+
46
+ ### Code
47
+
48
+ ```python
49
+ from markdownpal.blocks import CodeBlock
50
+
51
+ doc.append(CodeBlock("print('hello world')", lang="python"))
52
+ doc.append(CodeBlock("SELECT * FROM users;", lang="sql"))
53
+ doc.append(CodeBlock("plain code block, no highlighting"))
54
+ ```
55
+
56
+ ### Lists
57
+
58
+ ```python
59
+ from markdownpal.blocks import ULBlock, OLBlock, TaskListBlock
60
+
61
+ doc.append(ULBlock(["Apples", "Bananas", "Cherries"]))
62
+
63
+ doc.append(OLBlock(["Install", "Configure", "Run"]))
64
+
65
+ doc.append(TaskListBlock([
66
+ ("Write tests", True),
67
+ ("Write code", True),
68
+ ("Deploy", False),
69
+ ]))
70
+ ```
71
+
72
+ ### Table
73
+
74
+ ```python
75
+ from markdownpal.blocks import TableBlock
76
+
77
+ doc.append(TableBlock(
78
+ headers=["Name", "Role", "Status"],
79
+ rows=[
80
+ ["Alice", "Engineer", "✅ Active"],
81
+ ["Bob", "Designer", "✅ Active"],
82
+ ["Carol", "PM", "🔄 Onboarding"],
83
+ ]
84
+ ))
85
+ ```
86
+
87
+ ### Images & Links
88
+
89
+ ```python
90
+ from markdownpal.blocks import ImageBlock, LinkBlock
91
+
92
+ doc.append(ImageBlock(src="https://example.com/logo.png", alt="Project Logo"))
93
+ doc.append(ImageBlock(src="diagram.png")) # alt is optional
94
+ doc.append(LinkBlock(text="Documentation", url="https://example.com/docs"))
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Inline Helpers
100
+
101
+ Inline helpers return strings and can be composed or embedded inside any block content:
102
+
103
+ ```python
104
+ from markdownpal.inline import bold, italic, code, strikethrough
105
+
106
+ bold("important") # **important**
107
+ italic("note") # *note*
108
+ code("os.path.join()") # `os.path.join()`
109
+ strikethrough("deprecated") # ~~deprecated~~
110
+
111
+ # Composable
112
+ bold(italic("emphasis")) # ***emphasis***
113
+
114
+ # Embed in blocks
115
+ TextBlock(f"See {code('render()')} for details.")
116
+ H2Block(f"API {italic('Reference')}")
117
+ ```
118
+
119
+ ---
120
+
121
+ ## Render to String
122
+
123
+ Use `render()` to get the Markdown string directly without saving to disk:
124
+
125
+ ```python
126
+ doc = MarkdownDocument()
127
+ doc.append(H1Block("Report"))
128
+ doc.append(TextBlock("Generated automatically."))
129
+
130
+ output = doc.render()
131
+ print(output)
132
+ # # Report
133
+ #
134
+ # Generated automatically.
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Save to File
140
+
141
+ ```python
142
+ doc.save("report.md") # relative path
143
+ doc.save("/tmp/docs/report.md") # absolute path
144
+ ```
145
+
146
+ Files are written in UTF-8 and fully support international characters and emoji:
147
+
148
+ ```python
149
+ doc.append(H1Block("项目文档"))
150
+ doc.append(TextBlock("支持中文、日本語、한국어 및 emoji 🎉"))
151
+ doc.save("国际化.md")
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Complete Example
157
+
158
+ ```python
159
+ from markdownpal import Document
160
+ from markdownpal.blocks import (
161
+ H1Block, H2Block, H3Block,
162
+ TextBlock, CodeBlock, TableBlock,
163
+ ULBlock, TaskListBlock, HRBlock,
164
+ )
165
+ from markdownpal.inline import bold, italic, code
166
+
167
+ doc = Document()
168
+
169
+ doc.append(H1Block("Project Changelog"))
170
+ doc.append(TextBlock(f"All notable changes are documented here. Format based on {bold('Keep a Changelog')}."))
171
+ doc.append(HRBlock())
172
+
173
+ doc.append(H2Block("v1.2.0 — 2026-04-12"))
174
+ doc.append(H3Block("Added"))
175
+ doc.append(ULBlock([
176
+ f"{code('TaskListBlock')} for checkbox lists",
177
+ "UTF-8 file output via save()",
178
+ "Inline helpers: bold, italic, code, strikethrough",
179
+ ]))
180
+
181
+ doc.append(H3Block("Fixed"))
182
+ doc.append(ULBlock([
183
+ f"{code('QuoteBlock')} now correctly handles multi-line text",
184
+ ]))
185
+
186
+ doc.append(H2Block("Compatibility"))
187
+ doc.append(TableBlock(
188
+ headers=["Python", "Supported"],
189
+ rows=[
190
+ ["3.9", "✅"],
191
+ ["3.10", "✅"],
192
+ ["3.11", "✅"],
193
+ ["3.12", "✅"],
194
+ ]
195
+ ))
196
+
197
+ doc.append(H2Block("Installation"))
198
+ doc.append(CodeBlock("pip install markdownpal", lang="bash"))
199
+
200
+ doc.save("CHANGELOG.md")
201
+ ```
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rogerstacker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,261 @@
1
+ Metadata-Version: 2.4
2
+ Name: markdownpal
3
+ Version: 0.1.0
4
+ Summary: A pure-Python library for programmatically generating Markdown files.
5
+ Project-URL: Homepage, https://github.com/rogerstacker/markdownpal
6
+ Project-URL: Repository, https://github.com/rogerstacker/markdownpal
7
+ Project-URL: Bug Tracker, https://github.com/rogerstacker/markdownpal/issues
8
+ Author-email: Rogerstacker <rogerstacker3rd@gmail.com>
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 Rogerstacker
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: builder,document,generator,markdown
32
+ Classifier: Intended Audience :: Developers
33
+ Classifier: License :: OSI Approved :: MIT License
34
+ Classifier: Operating System :: OS Independent
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.9
37
+ Classifier: Programming Language :: Python :: 3.10
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Topic :: Text Processing :: Markup
41
+ Requires-Python: >=3.9
42
+ Provides-Extra: dev
43
+ Requires-Dist: pytest>=7.0; extra == 'dev'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # MarkdownPal
47
+
48
+ A pure-Python library for programmatically generating Markdown (`.md`) files via a clean, block-based document builder API.
49
+
50
+ [![Python](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/)
51
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
52
+
53
+ ---
54
+
55
+ ## Features
56
+
57
+ - **Block-based API** — compose documents from typed, self-contained block objects
58
+ - **Inline formatting helpers** — `bold()`, `italic()`, `code()`, `strikethrough()`
59
+ - **Full block support** — headings, paragraphs, quotes, code, lists, tables, images, links
60
+ - **Save to file** — UTF-8 output with full support for international characters and emoji
61
+ - **Zero dependencies** — no third-party packages required
62
+ - **Python 3.9+**
63
+
64
+ ---
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ pip3 install markdownpal
70
+ ```
71
+
72
+ ---
73
+
74
+ ## Quick Start
75
+
76
+ ```python
77
+ from markdownpal import Document
78
+ from markdownpal.blocks import H1Block, H2Block, TextBlock, CodeBlock, ULBlock
79
+ from markdownpal.inline import bold
80
+
81
+ doc = Document()
82
+
83
+ doc.append(H1Block("My Project"))
84
+ doc.append(TextBlock(f"A {bold('simple')} example of MarkdownPal."))
85
+ doc.append(H2Block("Installation"))
86
+ doc.append(CodeBlock("pip install markdownpal", lang="bash"))
87
+ doc.append(H2Block("Features"))
88
+ doc.append(ULBlock(["Zero dependencies", "Clean API", "Python 3.9+"]))
89
+
90
+ doc.save("output.md")
91
+ ```
92
+
93
+ Output (`output.md`):
94
+
95
+ ```markdown
96
+ # My Project
97
+
98
+ A **simple** example of MarkdownPal.
99
+
100
+ ## Installation
101
+
102
+ ```bash
103
+ pip install markdownpal
104
+ ```
105
+
106
+ ## Features
107
+
108
+ - Zero dependencies
109
+ - Clean API
110
+ - Python 3.9+
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Block Reference
116
+
117
+ ### Headings
118
+
119
+ ```python
120
+ from markdownpal.blocks import H1Block, H2Block, H3Block, H4Block, H5Block, H6Block
121
+
122
+ doc.append(H1Block("Title")) # # Title
123
+ doc.append(H2Block("Section")) # ## Section
124
+ doc.append(H3Block("Subsection")) # ### Subsection
125
+ ```
126
+
127
+ ### Text
128
+
129
+ ```python
130
+ from markdownpal.blocks import TextBlock, QuoteBlock, HRBlock, CommentBlock
131
+
132
+ doc.append(TextBlock("A plain paragraph."))
133
+ doc.append(QuoteBlock("A blockquote.\nSpanning multiple lines."))
134
+ doc.append(HRBlock()) # ---
135
+ doc.append(CommentBlock("Hidden in rendered output.")) # <!-- ... -->
136
+ ```
137
+
138
+ ### Code
139
+
140
+ ```python
141
+ from markdownpal.blocks import CodeBlock
142
+
143
+ doc.append(CodeBlock("print('hello')", lang="python"))
144
+ doc.append(CodeBlock("SELECT * FROM users;", lang="sql"))
145
+ doc.append(CodeBlock("no language specified"))
146
+ ```
147
+
148
+ ### Lists
149
+
150
+ ```python
151
+ from markdownpal.blocks import ULBlock, OLBlock, TaskListBlock
152
+
153
+ doc.append(ULBlock(["Apples", "Bananas", "Cherries"]))
154
+
155
+ doc.append(OLBlock(["Install", "Configure", "Run"]))
156
+
157
+ doc.append(TaskListBlock([
158
+ ("Write tests", True),
159
+ ("Write code", True),
160
+ ("Deploy", False),
161
+ ]))
162
+ ```
163
+
164
+ ### Table
165
+
166
+ ```python
167
+ from markdownpal.blocks import TableBlock
168
+
169
+ doc.append(TableBlock(
170
+ headers=["Name", "Role", "Status"],
171
+ rows=[
172
+ ["Alice", "Engineer", "Active"],
173
+ ["Bob", "Designer", "Active"],
174
+ ]
175
+ ))
176
+ ```
177
+
178
+ ### Images & Links
179
+
180
+ ```python
181
+ from markdownpal.blocks import ImageBlock, LinkBlock
182
+
183
+ doc.append(ImageBlock(src="logo.png", alt="Project Logo"))
184
+ doc.append(LinkBlock(text="Documentation", url="https://example.com/docs"))
185
+ ```
186
+
187
+ ---
188
+
189
+ ## Inline Helpers
190
+
191
+ Inline helpers return plain strings and can be embedded inside any block content:
192
+
193
+ ```python
194
+ from markdownpal.inline import bold, italic, code, strikethrough
195
+
196
+ bold("important") # **important**
197
+ italic("note") # *note*
198
+ code("os.path.join()") # `os.path.join()`
199
+ strikethrough("deprecated") # ~~deprecated~~
200
+
201
+ # Composable
202
+ bold(italic("emphasis")) # ***emphasis***
203
+
204
+ # Embed in blocks
205
+ doc.append(TextBlock(f"Call {code('render()')} to get the output string."))
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Document API
211
+
212
+ ```python
213
+ doc = Document()
214
+ doc.append(block) # Add a Block instance
215
+ doc.render() # Returns the full Markdown string
216
+ doc.save("out.md") # Writes UTF-8 Markdown file to disk
217
+ ```
218
+
219
+ `append()` raises `TypeError` if the argument is not a `Block` instance.
220
+ `render()` joins all blocks with a blank line (`\n\n`) between them.
221
+
222
+ ---
223
+
224
+ ## Project Structure
225
+
226
+ ```
227
+ markdownpal/
228
+ ├── __init__.py # Top-level public API
229
+ ├── document.py # Document class
230
+ ├── inline.py # Inline format helpers
231
+ └── blocks/
232
+ ├── base.py # Block abstract base class
233
+ ├── heading.py # H1Block ~ H6Block
234
+ ├── text.py # TextBlock, QuoteBlock, HRBlock, CommentBlock
235
+ ├── code.py # CodeBlock
236
+ ├── list_.py # ULBlock, OLBlock, TaskListBlock
237
+ ├── table.py # TableBlock
238
+ └── media.py # ImageBlock, LinkBlock
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Development
244
+
245
+ ```bash
246
+ # Clone the repository
247
+ git clone https://github.com/rogerstacker/markdownpal.git
248
+ cd markdownpal
249
+
250
+ # Install dev dependencies
251
+ pip3 install -e ".[dev]"
252
+
253
+ # Run tests
254
+ pytest
255
+ ```
256
+
257
+ ---
258
+
259
+ ## License
260
+
261
+ [MIT](LICENSE) © 2026 Rogerstacker